From 03bcf7bfc8f39b45edd812f1e21d9a433063a921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20B=C3=B6ckenkamp?= Date: Wed, 10 Apr 2013 15:16:46 +0200 Subject: [PATCH] Removed OVP-related (source) files/code (backend discarded). Change-Id: Ibf8065d9fe760640e5744896b764f9ebb6d2fa69 --- CMakeLists.txt | 6 +- cmake/ovp.cmake | 5 - doc/fail-structure.txt | 26 +- doc/how-to-build.txt | 19 - doc/todo.txt | 20 +- simulators/ovp/CMakeLists.txt | 56 - simulators/ovp/OVPCpu.hpp | 144 - simulators/ovp/OVPPlatform.cc | 57 - simulators/ovp/OVPPlatform.hpp | 63 - simulators/ovp/OVPStatusRegister.hpp | 51 - simulators/ovp/README | 7 - simulators/ovp/armmModel/CMakeLists.txt | 98 - simulators/ovp/armmModel/Makefile | 5 - .../armmModel/armAttributeEntriesThumb16.h | 245 - .../armmModel/armAttributeEntriesThumb32.h | 635 -- simulators/ovp/armmModel/armBitMacros.h | 43 - simulators/ovp/armmModel/armBus.c | 63 - simulators/ovp/armmModel/armConfig.h | 146 - simulators/ovp/armmModel/armDebug.h | 46 - simulators/ovp/armmModel/armDecode.h | 62 - .../ovp/armmModel/armDecodeEntriesThumb16.h | 138 - .../ovp/armmModel/armDecodeEntriesThumb32.h | 390 -- simulators/ovp/armmModel/armDecodeThumb.h | 57 - simulators/ovp/armmModel/armDecodeTypes.h | 762 --- simulators/ovp/armmModel/armDisassemble.h | 50 - .../ovp/armmModel/armDisassembleFormats.h | 213 - simulators/ovp/armmModel/armEmit.h | 540 -- simulators/ovp/armmModel/armExceptionTypes.h | 120 - simulators/ovp/armmModel/armExceptions.h | 156 - simulators/ovp/armmModel/armFPConstants.h | 108 - simulators/ovp/armmModel/armFunctions.h | 93 - simulators/ovp/armmModel/armInfo.c | 66 - simulators/ovp/armmModel/armMessage.h | 53 - simulators/ovp/armmModel/armMode.h | 83 - simulators/ovp/armmModel/armMorph.h | 139 - simulators/ovp/armmModel/armMorphEntries.h | 304 - simulators/ovp/armmModel/armMorphFunctions.h | 240 - simulators/ovp/armmModel/armRegisters.h | 122 - simulators/ovp/armmModel/armStructure.h | 359 -- simulators/ovp/armmModel/armSys.h | 128 - simulators/ovp/armmModel/armSysRegisters.h | 1026 ---- simulators/ovp/armmModel/armTypeRefs.h | 46 - simulators/ovp/armmModel/armUtils.h | 136 - simulators/ovp/armmModel/armVFP.h | 80 - simulators/ovp/armmModel/armVM.h | 116 - simulators/ovp/armmModel/armVariant.h | 107 - simulators/ovp/armmModel/armmAttrs.c | 135 - simulators/ovp/armmModel/armmConfigList.c | 488 -- simulators/ovp/armmModel/armmDebug.c | 683 --- simulators/ovp/armmModel/armmDecode.c | 76 - simulators/ovp/armmModel/armmDecodeThumb.c | 2725 --------- simulators/ovp/armmModel/armmDisassemble.c | 929 --- simulators/ovp/armmModel/armmDoc.c | 81 - simulators/ovp/armmModel/armmDoc.h | 43 - simulators/ovp/armmModel/armmEmit.c | 1123 ---- simulators/ovp/armmModel/armmExceptions.c | 2378 -------- simulators/ovp/armmModel/armmMain.c | 284 - simulators/ovp/armmModel/armmMorphFunctions.c | 5141 ----------------- simulators/ovp/armmModel/armmMorphTable.c | 423 -- simulators/ovp/armmModel/armmParameters.c | 166 - simulators/ovp/armmModel/armmParameters.h | 88 - simulators/ovp/armmModel/armmSemiHost.c | 182 - simulators/ovp/armmModel/armmSys.c | 1683 ------ simulators/ovp/armmModel/armmUtils.c | 509 -- simulators/ovp/armmModel/armmVFP.c | 876 --- simulators/ovp/armmModel/armmVM.c | 1271 ---- simulators/ovp/armmModel/export.def | 3 - simulators/ovp/armmModel/failSALlink.cc | 15 - simulators/ovp/cortexM3/CMakeLists.txt | 15 - simulators/ovp/cortexM3/platform/platform.cc | 415 -- simulators/ovp/cortexM3/platform/platform.hpp | 36 - simulators/ovp/cortexM3/platform/statreg.hpp | 92 - .../mmc/flakyMemory/1.0/model/CMakeLists.txt | 12 - .../mmc/flakyMemory/1.0/model/flipBits.cpp | 11 - .../mmc/flakyMemory/1.0/model/flipBits.h | 10 - .../mmc/flakyMemory/1.0/model/model.cpp | 189 - simulators/ovp/setImperas.sh | 11 - simulators/ovp/statusmsg/CMakeLists.txt | 14 - .../ovp/statusmsg/OVPStatusMessage.proto | 10 - simulators/ovp/statusmsg/protogen.sh | 2 - simulators/ovp/test1/CMakeLists.txt | 13 - simulators/ovp/test1/application.elf | Bin 88526 -> 0 bytes .../ovp/test1/application/application.c | 20 - .../ovp/test1/platform/beforeInstruction.cpp | 91 - .../ovp/test1/platform/beforeInstruction.hpp | 46 - simulators/ovp/test1/platform/flakyMemory.cpp | 66 - simulators/ovp/test1/platform/flakyMemory.hpp | 21 - simulators/ovp/test1/platform/platform.cpp | 90 - src/core/config/CMakeLists.txt | 2 +- src/core/config/VariantConfig.hpp.in | 1 - src/core/sal/CMakeLists.txt | 11 - src/core/sal/ConcreteCPU.hpp | 2 - src/core/sal/SALConfig.cc | 3 +- src/core/sal/SALConfig.hpp | 2 - src/core/sal/SALInst.hpp | 8 - src/core/sal/ovp/FailOVPInit.ah | 23 - src/core/sal/ovp/OVPConfig.hpp | 20 - src/core/sal/ovp/OVPController.cc | 132 - src/core/sal/ovp/OVPController.hpp | 73 - src/core/sal/ovp/OVPMemory.hpp | 67 - src/core/sal/ovp/OVPRegister.hpp | 76 - 101 files changed, 22 insertions(+), 28293 deletions(-) delete mode 100644 cmake/ovp.cmake delete mode 100644 simulators/ovp/CMakeLists.txt delete mode 100644 simulators/ovp/OVPCpu.hpp delete mode 100644 simulators/ovp/OVPPlatform.cc delete mode 100644 simulators/ovp/OVPPlatform.hpp delete mode 100644 simulators/ovp/OVPStatusRegister.hpp delete mode 100644 simulators/ovp/README delete mode 100644 simulators/ovp/armmModel/CMakeLists.txt delete mode 100644 simulators/ovp/armmModel/Makefile delete mode 100644 simulators/ovp/armmModel/armAttributeEntriesThumb16.h delete mode 100644 simulators/ovp/armmModel/armAttributeEntriesThumb32.h delete mode 100644 simulators/ovp/armmModel/armBitMacros.h delete mode 100644 simulators/ovp/armmModel/armBus.c delete mode 100644 simulators/ovp/armmModel/armConfig.h delete mode 100644 simulators/ovp/armmModel/armDebug.h delete mode 100644 simulators/ovp/armmModel/armDecode.h delete mode 100644 simulators/ovp/armmModel/armDecodeEntriesThumb16.h delete mode 100644 simulators/ovp/armmModel/armDecodeEntriesThumb32.h delete mode 100644 simulators/ovp/armmModel/armDecodeThumb.h delete mode 100644 simulators/ovp/armmModel/armDecodeTypes.h delete mode 100644 simulators/ovp/armmModel/armDisassemble.h delete mode 100644 simulators/ovp/armmModel/armDisassembleFormats.h delete mode 100644 simulators/ovp/armmModel/armEmit.h delete mode 100644 simulators/ovp/armmModel/armExceptionTypes.h delete mode 100644 simulators/ovp/armmModel/armExceptions.h delete mode 100644 simulators/ovp/armmModel/armFPConstants.h delete mode 100644 simulators/ovp/armmModel/armFunctions.h delete mode 100644 simulators/ovp/armmModel/armInfo.c delete mode 100644 simulators/ovp/armmModel/armMessage.h delete mode 100644 simulators/ovp/armmModel/armMode.h delete mode 100644 simulators/ovp/armmModel/armMorph.h delete mode 100644 simulators/ovp/armmModel/armMorphEntries.h delete mode 100644 simulators/ovp/armmModel/armMorphFunctions.h delete mode 100644 simulators/ovp/armmModel/armRegisters.h delete mode 100644 simulators/ovp/armmModel/armStructure.h delete mode 100644 simulators/ovp/armmModel/armSys.h delete mode 100644 simulators/ovp/armmModel/armSysRegisters.h delete mode 100644 simulators/ovp/armmModel/armTypeRefs.h delete mode 100644 simulators/ovp/armmModel/armUtils.h delete mode 100644 simulators/ovp/armmModel/armVFP.h delete mode 100644 simulators/ovp/armmModel/armVM.h delete mode 100644 simulators/ovp/armmModel/armVariant.h delete mode 100644 simulators/ovp/armmModel/armmAttrs.c delete mode 100644 simulators/ovp/armmModel/armmConfigList.c delete mode 100644 simulators/ovp/armmModel/armmDebug.c delete mode 100644 simulators/ovp/armmModel/armmDecode.c delete mode 100644 simulators/ovp/armmModel/armmDecodeThumb.c delete mode 100644 simulators/ovp/armmModel/armmDisassemble.c delete mode 100644 simulators/ovp/armmModel/armmDoc.c delete mode 100644 simulators/ovp/armmModel/armmDoc.h delete mode 100644 simulators/ovp/armmModel/armmEmit.c delete mode 100644 simulators/ovp/armmModel/armmExceptions.c delete mode 100644 simulators/ovp/armmModel/armmMain.c delete mode 100644 simulators/ovp/armmModel/armmMorphFunctions.c delete mode 100644 simulators/ovp/armmModel/armmMorphTable.c delete mode 100644 simulators/ovp/armmModel/armmParameters.c delete mode 100644 simulators/ovp/armmModel/armmParameters.h delete mode 100644 simulators/ovp/armmModel/armmSemiHost.c delete mode 100644 simulators/ovp/armmModel/armmSys.c delete mode 100644 simulators/ovp/armmModel/armmUtils.c delete mode 100644 simulators/ovp/armmModel/armmVFP.c delete mode 100644 simulators/ovp/armmModel/armmVM.c delete mode 100755 simulators/ovp/armmModel/export.def delete mode 100644 simulators/ovp/armmModel/failSALlink.cc delete mode 100644 simulators/ovp/cortexM3/CMakeLists.txt delete mode 100644 simulators/ovp/cortexM3/platform/platform.cc delete mode 100644 simulators/ovp/cortexM3/platform/platform.hpp delete mode 100644 simulators/ovp/cortexM3/platform/statreg.hpp delete mode 100644 simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/CMakeLists.txt delete mode 100644 simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.cpp delete mode 100644 simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.h delete mode 100644 simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/model.cpp delete mode 100644 simulators/ovp/setImperas.sh delete mode 100644 simulators/ovp/statusmsg/CMakeLists.txt delete mode 100644 simulators/ovp/statusmsg/OVPStatusMessage.proto delete mode 100755 simulators/ovp/statusmsg/protogen.sh delete mode 100644 simulators/ovp/test1/CMakeLists.txt delete mode 100755 simulators/ovp/test1/application.elf delete mode 100644 simulators/ovp/test1/application/application.c delete mode 100644 simulators/ovp/test1/platform/beforeInstruction.cpp delete mode 100644 simulators/ovp/test1/platform/beforeInstruction.hpp delete mode 100644 simulators/ovp/test1/platform/flakyMemory.cpp delete mode 100644 simulators/ovp/test1/platform/flakyMemory.hpp delete mode 100644 simulators/ovp/test1/platform/platform.cpp delete mode 100644 src/core/sal/ovp/FailOVPInit.ah delete mode 100644 src/core/sal/ovp/OVPConfig.hpp delete mode 100644 src/core/sal/ovp/OVPController.cc delete mode 100644 src/core/sal/ovp/OVPController.hpp delete mode 100644 src/core/sal/ovp/OVPMemory.hpp delete mode 100644 src/core/sal/ovp/OVPRegister.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d45f5923..06b46f71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,9 +30,8 @@ include(doxygen) #### Backend selection #### OPTION( BUILD_BOCHS "Build Bochs Variant?" ON) OPTION( BUILD_GEM5 "Build gem5 Variant?" OFF) -OPTION( BUILD_OVP "Build OVP Variant?" OFF) OPTION( BUILD_QEMU "Build QEMU Variant?" OFF) -OPTION( BUILD_T32 "Build Lauterbach Trace32 Variant?" OFF) +OPTION( BUILD_T32 "Build Lauterbach Trace32 Variant?" OFF) OPTION( BUILD_X86 "Build for x86 guests?" ON) OPTION( BUILD_ARM "Build for ARM guests?" OFF) @@ -47,8 +46,6 @@ if(BUILD_BOCHS) elseif(BUILD_GEM5) include_directories(simulators/gem5/src simulators/gem5/build/ARM) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -DTRACING_ON") -elseif(BUILD_OVP) - add_subdirectory(simulators/ovp) elseif(BUILD_QEMU) include_directories(simulators) elseif(BUILD_T32) @@ -73,7 +70,6 @@ add_subdirectory(src) #### Backend-related build system stuff include(bochs) include(gem5) -include(ovp) include(qemu) include(t32) diff --git a/cmake/ovp.cmake b/cmake/ovp.cmake deleted file mode 100644 index d24ce067..00000000 --- a/cmake/ovp.cmake +++ /dev/null @@ -1,5 +0,0 @@ -#### OVP-specific stuff -if(BUILD_OVP) - message(STATUS "[${PROJECT_NAME}] Building OVP variant ...") - SET(VARIANT ovp) -endif(BUILD_OVP) diff --git a/doc/fail-structure.txt b/doc/fail-structure.txt index c170d4be..26faec4f 100644 --- a/doc/fail-structure.txt +++ b/doc/fail-structure.txt @@ -11,21 +11,31 @@ fail: Fail* parent directory, containing all source & configuration files (${FA |-scripts: python/shell scripts for Fail*-compilation and experiment distribution |-simulators: parent directory of simulators supported by Fail* (may still be WIP) |-bochs: source files of the (modified) Bochs x86 simulator backend - |-ovp: source files of the Open Virtual Platform simulator backend + |-gem5: source files of the gem5 simulator backend +|-debuggers: parent directory of debuggers supported by Fail* (may still be WIP) + |-gdb: source files related to the GNU gdb debugger + |-t32: source files related to the Lauterbach T32 debugger |-src: C/C++/AspectC++ source files related to Fail*, experiments and plugins |-core: core source files forming the Fail* framework |-util: utility classes and miscellaneous helper functions |-config: CMake configuration files, defining the Fail* components and variant |-sal: source file forming the Simulator Abstraction Layer (backend-interface) - |-bochs: backend source files to the Bochs simulator - |-ovp: backend source files to the Open Virtual Platform simulator + |-bochs: backend source files of the Bochs simulator + |-gem5: backend source files of the gem5 simulator + |-qemu: backend source files of the QEMU simulator + |-t32: backend source files of the Lauterbach T32 debugger + |-arm: ARM-specific platform source files + |-x86: x86-specific platform source files + |-perf: performance-related source files (extensions); speeds up + Fail* <-> simulator interaction (e.g., when using breakpoints) |-cpn: campaign- (and therefore server-)related source files |-efw: experiment-framework- (and therefore client-)related source files - |-comm: communication related source files (these files are used by cpn and efw) - |-msg: Google protobuf message definitions used for communication purposes + |-comm: communication related source files (these files are used by cpn and efw), incl. + protobuf message definitions used for communication purposes |-experiments: experiment code files (within a new dir) need to be located here |-plugins: plugin code files (within a new dir) need to be located here -|-[build]: recommended location of your build-tree, generated files will be placed here +|-tools: Fail*-related tools, e.g., for tracing or fault-space pruning +|-[build]: recommended location of your build-tree, generated files will be placed here Some additional useful notes: @@ -40,8 +50,8 @@ Some additional useful notes: - CMake invokes the compiler with the following include directories: * ${FAIL_DIR}/src/core * ${BUILD_DIR}/src/core - When compiling the Bochs variant the following directory is added, too: - * ${FAIL_DIR}/simulators/bochs + When compiling the $SIMULATOR variant the following directory is added, too: + * ${FAIL_DIR}/simulators/$SIMULATOR These definitions simplify and shorten the include paths. ========================================================================================= diff --git a/doc/how-to-build.txt b/doc/how-to-build.txt index 0b43826b..50a4bf7d 100644 --- a/doc/how-to-build.txt +++ b/doc/how-to-build.txt @@ -184,25 +184,6 @@ Comparison IPS numbers are shown in the default "bochsrc". Headless bochsrc conf all aspects disabled, guest system executes endless loop, host CPU Xeon X5470 (3.33GHz): IPS: 66124283 average = 66964789 -Building OVP for ARM Cortex-M3: -********************************************************************** - -For the first time: ------------------------------------------------------------- - 1. Get a license from http://www.ovpworld.org/ - 2. Download the following files: - - Downloads -> Main OVP Download including OVPsim Simulator - - Downloads -> ARM -> ARM OVP Cortex-M Profile Model - -> Self contained ARM Cortex-M examples - -> ARM GNU GCC and GDB tools - 3. Install OVP by running the self-extracting archives. - 4. Get Sourcery CodeBench Lite Edition from - http://www.mentor.com/embedded-software/codesourcery - (ARM processors -> EABI release) - 5. Install the self-extracting archive, or use the installation in - /fs/proj/compiler/codesourcery-arm-eabi (DO, ios/kos) -TODO: Source setup.sh, setupImperas ... -TODO: Fix Hard-coded paths Building gem5: ********************************************************************** diff --git a/doc/todo.txt b/doc/todo.txt index 2d3d0999..bfe71632 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -117,7 +117,7 @@ Buildsystem: (verwendeter Compiler, Installationsverzeichnis, ...), den Rest in einem brauchbaren Konfigurationswerkzeug mit Ausdrucksmöglichkeiten für Merkmalmodelle, Abhängigkeiten, Mehrfachauswahl etc. (kconfig?) - * Bochs / OVP / Gem5 sind Alternativen, nicht beide anschaltbar + * Bochs / T32 / Gem5 sind Alternativen, nicht beide anschaltbar -> Cmake-Combo-Box (ggf. noch an anderen Stellen einsetzbar) http://www.kitware.com/blog/home/post/82 - Hinzufügen eines neuen Experiments konkreter dokumentieren (how-to-build.txt?) @@ -218,21 +218,3 @@ Theorie TODO ========================================================================================== - Problem Fork von FI Tools -> Merging eklig. -> Liste mit konkreten Beispielen - - -========================================================================================== -FailOVP-Bausteine TODO -========================================================================================== -Wer gerade an was arbeitet, steht in Klammern hinter dem TODO. - -Abstraktionen: - - save/restore implementieren -> Speicher-, Register-, Timer-, ??- Zustaende - -Sonstiges: - - Sections aus ELF Datei extrahieren, entsprechende Speicherbereiche (generisch) anlegen (rz) - - Symbole aus ELF extrahieren -> Adressen von globalen Objekten/Funktionen in Experimenten angeben (rz) - - Prozessormodell per cmake cleanen und neu bauen (mh) - - CiAO ELF in OVP ausfuehren - -Erledigt: - - diff --git a/simulators/ovp/CMakeLists.txt b/simulators/ovp/CMakeLists.txt deleted file mode 100644 index a93a566c..00000000 --- a/simulators/ovp/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ - - - # PreDefined environment variables (setupImperas) - # IMPERAS_HOME - # IMPERAS_ARCA - - # And the variables set in Imperas/bin/Makefile.include - # IMPERAS_LIB - # IMPERAS_BIN - # IMPERAS_VMISTUBS - # IMPERAS_VMIINC - # SHRSUF - # -#TODO test ist IMPERAS_HOME is set. - - -message(STATUS "Imperas Home: $ENV{IMPERAS_HOME}") -message(STATUS "Imperas License: $ENV{IMPERASD_LICENSE_FILE}") - - -message(STATUS "Arch: $ENV{IMPERAS_ARCH}") -#message(STATUS "VLNV: $ENV{IMPERAS_VLNV}") -#set(IMPERAS_LIB $ENV{IMPERAS_HOME}/lib/$ENV{IMPERAS_ARCH}) - -set(IMPERAS_BIN $ENV{IMPERAS_HOME}/bin/$ENV{IMPERAS_ARCH}) -set(IMPERAS_VMISTUBS ${IMPERAS_BIN}/vmiStubs.a) -set(IMPERAS_VMIINC - -I$ENV{IMPERAS_HOME}/ImpPublic/include/host -) - -## This is needed when building a shared library -set(HOST_LDFLAGS "-Wl,--version-script=$ENV{IMPERAS_HOME}/ImperasLib/source/buildutils/version.script") - -## This is needed by a platform executable -set(SIM_LDFLAGS $ENV{IMPERAS_HOME}/bin/$ENV{IMPERAS_ARCH}/libRuntimeLoader.so) - - -include_directories(${CMAKE_SOURCE_DIR}) -include_directories(${CMAKE_SOURCE_DIR}/src/core) -include_directories(${CMAKE_BINARY_DIR}) -include_directories(${CMAKE_BINARY_DIR}/src/core) -include_directories($ENV{IMPERAS_HOME}/ImpPublic/include/host) - -#add_subdirectory(ovpworld.org/mmc/flakyMemory/1.0/model) -add_subdirectory(cortexM3) -add_subdirectory(statusmsg) - -include(ExternalProject) -#### Put resulting (model) library file in /lib #### -ExternalProject_Add( - OVParmmModel - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/armmModel - INSTALL_COMMAND "" - CMAKE_ARGS -DFAIL_BASE=${CMAKE_SOURCE_DIR} -DLIBRARY_OUTPUT_PATH=${LIBRARY_OUTPUT_PATH} -) - diff --git a/simulators/ovp/OVPCpu.hpp b/simulators/ovp/OVPCpu.hpp deleted file mode 100644 index 512a60d5..00000000 --- a/simulators/ovp/OVPCpu.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef _OVPCpu_HPP_ -#define _OVPCpu_HPP_ - -#include "icm/icmCpuManager.hpp" -#include "sal/Register.hpp" -#include "OVPPlatform.hpp" - -extern OVPPlatform ovpplatform; - - -using namespace icmCpuManager; - -/** - * \class OVPCpu - * Abstract class which contains methods OVP platforms must implement. - * As there is the possibility to create different platforms this class - * is an interface for the OVPPlatform. - */ -class OVPCpu { - protected: - icmPlatform *platform; - icmProcessorObject *cpu; - icmAttrListObject *attrList; - icmProcessorP processorP; - - // for MMC - icmMmcObject *mmcInstr; - icmMmcObject *mmcData; - icmBusObject *instrBus; - icmBusObject *dataBus; - icmBusObject *mainBus; - icmMemoryObject *icmMem0; - icmMemoryObject *icmMem1; - icmMemoryObject *icmMem2; - - icmRegInfoP rid_sp; - - public: - unsigned char *mem; - Int16 *textmem; - size_t offset; - size_t memSize; - size_t textOffset; - size_t textMemSize; - - /** - * Initialize platform. - * @param gdb set if GDB functionality should be enabled - */ - virtual void init(bool) = 0; - - /** - * Simulate the platform - * @param app Name/Path to the application to run - */ - virtual int startSimulation(const char*) = 0; - - /** - * Create a full MMC to have memory control. - * @param vlnRoot Path to OVP model. Default: 0 -> default OVP path will be taken - */ - virtual void createFullMMC(const char *) = 0; - - /** - * Set general purpose register in SAL - */ - virtual void makeGPRegister() = 0; - - /** - * Set status register in SAL - */ - virtual void makeSTRegister() = 0; - - /** - * Set program counter register in SAL - */ - virtual void makePCRegister() = 0; - - /** - * Create local mirrored memory to handle memory manipulations - * during the memory callback - * @param sizeText Size of the text segment - * @param offText Address the text segment starts - * @param sizeMem Size of the other segments - * @param offMem Address the other segments start - */ - virtual void makeCallbackMemory(size_t sizeText, size_t offText, size_t sizeMem, size_t offMem) = 0; - - /** - * Saves cpu status in file at given path - * @param path path to store file - */ - virtual void save(const string& path) = 0; - - /** - * Restore cpu status from file at given path - * @param path path to store file - */ - virtual void restore(const string& path) = 0; - /** - * Returns the private icmProcessorObject pointer needed for some OVP action - * @return icmProcessorObject - */ - - icmProcessorObject *getProcessor() { - return cpu; - } - - /** - * Returns the private ProcessorP struct needed for some OVP action - * @return ProcessorP - */ - icmProcessorP getProcessorP() { - return processorP; - } - - /** - * Set the pointer to the stack pointer register - * @param reg icmRegInfoP of the stack pointer register - */ - void setSPReg(icmRegInfoP reg) { - rid_sp = reg; - } - - /** - * Returns the private stack pointer register pointer - * @return stack pointer register - */ - icmRegInfoP getSPReg() { - return rid_sp; - } - - /** - * Fills the callback memory with program data. This function - * must be called after the application is loaded to local memory - * and before the start of the simulation. - */ - void fillCallbackMemory() { - mainBus->read(offset, mem, memSize, cpu); - mainBus->read(textOffset, textmem, textMemSize, cpu); - } -}; - -#endif diff --git a/simulators/ovp/OVPPlatform.cc b/simulators/ovp/OVPPlatform.cc deleted file mode 100644 index 05cb5802..00000000 --- a/simulators/ovp/OVPPlatform.cc +++ /dev/null @@ -1,57 +0,0 @@ -#include "OVPCpu.hpp" -#include "OVPStatusRegister.hpp" -#include "OVPPlatform.hpp" -#include "sal/Register.hpp" -#include "sal/SALInst.hpp" - - -OVPPlatform ovpplatform; - -// current CPU -OVPCpu *platform; -icmProcessorObject *processor; -icmProcessorP cpuP; - -void OVPPlatform::setCpu(void *ovpcpu) { - platform = (OVPCpu *)ovpcpu; - processor = platform->getProcessor(); - cpuP = processor->getProcessorP(); -} - -void OVPPlatform::setRegisterData(void * link, unsigned int val) { - icmWriteRegInfoValue(cpuP, (icmRegInfoP)link, (void *) &val); -} - -unsigned int OVPPlatform::getRegisterData(void *link) { - unsigned int res; - - icmReadRegInfoValue(cpuP, (icmRegInfoP)link, (void *)&res); - return res; -} - -uint32_t OVPPlatform::getPC() { - return (uint32_t) processor->getPC(); -} - -void OVPPlatform::setPC(uint32_t val) { - processor->setPC(val); -} - - -uint32_t OVPPlatform::getSP() { - uint32_t res; - void *buf = &res; - - icmReadRegInfoValue(cpuP, platform->getSPReg(), buf); - - return res; - -} - -void OVPPlatform::save(const string& path) { - platform->save(path); -} - -void OVPPlatform::restore(const string& path) { - platform->restore(path); -} diff --git a/simulators/ovp/OVPPlatform.hpp b/simulators/ovp/OVPPlatform.hpp deleted file mode 100644 index cbcf0569..00000000 --- a/simulators/ovp/OVPPlatform.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __OVPPLATFORM_HPP__ -#define __OVPPLATFORM_HPP__ - -#include - -/** - * \class OVPPlatform - * OVPPlatform is the layer/interface which connects SAL and the OVP platform. - */ -class OVPPlatform { - -public: - /** - * The current OVP platform has to set a pointer to itself so that - * OVPPlatform can execute OVP functions using the correct platform - * @param ovpcpu void ptr to the OVPCpu object - */ - void setCpu(void *); - - /** - * Set value to a register - * @param link Pointer to the OVP register - * @param val Value the register is set to - */ - void setRegisterData(void *, unsigned int); - - /** - * Retrieves value from a register - * @param link Pointer to the OVP register - * @return value of the register - */ - unsigned int getRegisterData(void *); - - /** - * Get the program counter - * @return current program counter - */ - uint32_t getPC(); - - /** - * Set the program counter - */ - void setPC(uint32_t); - - /** - * Get the stack pointer - * @return current stack pointer - */ - uint32_t getSP(); - - /** - * Save cpu status - */ - void save(const string&); - - /** - * Restore cpu status - */ - void restore(const string&); - -}; - -#endif diff --git a/simulators/ovp/OVPStatusRegister.hpp b/simulators/ovp/OVPStatusRegister.hpp deleted file mode 100644 index c18894b8..00000000 --- a/simulators/ovp/OVPStatusRegister.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __OVP_STATUS_REGISTER_HPP__ - #define __OVP_STATUS_REGISTER_HPP__ - -#include "sal/ovp/OVPRegister.hpp" - -/** - * \class OVPStatusRegister - * Abstract class for status register implementation - */ -class OVPStatusRegister : public fail::OVPRegister { - protected: - - public: - OVPStatusRegister(uint32_t width, void *link) - : fail::OVPRegister(width, 32, link, fail::RT_ST) { } - ~OVPStatusRegister() {} - - virtual bool getSignFlag() const = 0; - virtual bool getZeroFlag() const = 0; - virtual bool getCarryFlag() const = 0; - virtual bool getOverflowFlag() const = 0; - - virtual void setSignFlag(bool) = 0; - virtual void setZeroFlag(bool) = 0; - virtual void setCarryFlag(bool) = 0; - virtual void setOverflowFlag(bool) = 0; - - /** - * Invert bit at specific position of status register - * @param pos position of bit to invert - */ -/* void invertBit(int pos) { - size_t val; - size_t chpos = 1 << pos; - - icmReadRegInfoValue(cpuP, cpsr, (void *)&val); - - // get bit - bool bit = (val >> pos) & 0x1; - - if(bit == 0) { - chpos = ~chpos; - val = val & chpos; - } else { - val = val | chpos; - } - - }*/ -}; - -#endif // __OVP_STATUS_REGISTER_HPP__ diff --git a/simulators/ovp/README b/simulators/ovp/README deleted file mode 100644 index c0917cf1..00000000 --- a/simulators/ovp/README +++ /dev/null @@ -1,7 +0,0 @@ -Env setzen: . ./setImperas.sh - -64 bit Systeme brauchen ia32-libs -evtl unter Ubuntu: ln -s /usr/lib32/libstdc++.so.6 /usr/lib32/libstdc++.so - -License Server in Env-Variable: -export IMPERASD_LICENSE_FILE=@faui49.informatik.uni-erlangen.de diff --git a/simulators/ovp/armmModel/CMakeLists.txt b/simulators/ovp/armmModel/CMakeLists.txt deleted file mode 100644 index d7c260d5..00000000 --- a/simulators/ovp/armmModel/CMakeLists.txt +++ /dev/null @@ -1,98 +0,0 @@ -Project(OVPCM3_Model) -cmake_minimum_required(VERSION 2.8) - - -message(STATUS "Imperas Home: $ENV{IMPERAS_HOME}") -message(STATUS "Imperas License: $ENV{IMPERASD_LICENSE_FILE}") - - -message(STATUS "Arch: $ENV{IMPERAS_ARCH}") -set(IMPERAS_BIN $ENV{IMPERAS_HOME}/bin/$ENV{IMPERAS_ARCH}) -set(IMPERAS_VMISTUBS ${IMPERAS_BIN}/vmiStubs.a) -set(IMPERAS_VMIINC - -I$ENV{IMPERAS_HOME}/ImpPublic/include/host -) - -## This is needed when building a shared library -set(HOST_LDFLAGS "-Wl,--version-script=$ENV{IMPERAS_HOME}/ImperasLib/source/buildutils/version.script") - -## This is needed by a platform executable -set(SIM_LDFLAGS $ENV{IMPERAS_HOME}/bin/$ENV{IMPERAS_ARCH}/libRuntimeLoader.so) - -message(STATUS "Fail* base dir included: ${FAIL_BASE}") -message(STATUS "Library output path: ${LIBRARY_OUTPUT_PATH}") -include_directories(${FAIL_BASE}) -include_directories($ENV{IMPERAS_HOME}/ImpPublic/include/host) - -set(CMAKE_C_COMPILER "gcc") -set(CMAKE_CXX_COMPILER "g++") - -#### Put resulting (model) library file in /lib #### - -set(SRCS - failSALlink.cc - armAttributeEntriesThumb16.h - armAttributeEntriesThumb32.h - armBitMacros.h - armBus.c - armConfig.h - armDebug.h - armDecodeEntriesThumb16.h - armDecodeEntriesThumb32.h - armDecode.h - armDecodeThumb.h - armDecodeTypes.h - armDisassembleFormats.h - armDisassemble.h - armEmit.h - armExceptions.h - armExceptionTypes.h - armFPConstants.h - armFunctions.h - armInfo.c - armmAttrs.c - armmConfigList.c - armmDebug.c - armmDecode.c - armmDecodeThumb.c - armmDisassemble.c - armmDoc.c - armmDoc.h - armmEmit.c - armMessage.h - armmExceptions.c - armmMain.c - armmMorphFunctions.c - armmMorphTable.c - armMode.h - armMorphEntries.h - armMorphFunctions.h - armMorph.h - armmParameters.c - armmParameters.h - armmSemiHost.c - armmSys.c - armmUtils.c - armmVFP.c - armmVM.c - armRegisters.h - armStructure.h - armSys.h - armSysRegisters.h - armTypeRefs.h - armUtils.h - armVariant.h - armVFP.h - armVM.h -) -add_definitions("-m32 ${IMPERAS_VMIINC}") -message(STATUS "armmModel ld flags: ${HOST_LDFLAGS}") -add_library(armmModel SHARED ${SRCS}) - - -#add_dependencies(armmModel SAL) -set_target_properties(armmModel PROPERTIES LINK_FLAGS "${HOST_LDFLAGS} -m32")# -L${CMAKE_BINARY_DIR}/lib -lSAL") - -#target_link_libraries(armmModel ${IMPERAS_VMISTUBS} ${LIBRARY_OUTPUT_PATH}/libSAL.a) -target_link_libraries(armmModel ${IMPERAS_VMISTUBS}) - diff --git a/simulators/ovp/armmModel/Makefile b/simulators/ovp/armmModel/Makefile deleted file mode 100644 index 1401e03d..00000000 --- a/simulators/ovp/armmModel/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -IMPERAS_HOME := $(shell getpath.exe "$(IMPERAS_HOME)") - -LDFLAGS+=-lm - -include $(IMPERAS_HOME)/ImperasLib/source/buildutils/Makefile.host diff --git a/simulators/ovp/armmModel/armAttributeEntriesThumb16.h b/simulators/ovp/armmModel/armAttributeEntriesThumb16.h deleted file mode 100644 index 60e12051..00000000 --- a/simulators/ovp/armmModel/armAttributeEntriesThumb16.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_ATTRIBUTE_ENTRIES_THUMB16_H -#define ARM_ATTRIBUTE_ENTRIES_THUMB16_H - -#include "armDisassembleFormats.h" - -// -// Attribute entries for 16-bit Thumb instructions like ADC -// -#define ATTR_SET_16_ADC(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_IT, r1:R3_0, r2:R3_3} - -// -// Attribute entries for 16-bit Thumb instructions like ADD (1) -// -#define ATTR_SET_16_ADD1(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_IT, r1:R3_0, r2:R3_3, cs:CS_U_3_6} - -// -// Attribute entries for 16-bit Thumb instructions like ADD (2) -// -#define ATTR_SET_16_ADD2(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_IT, r1:R3_8, cs:CS_U_8_0} - -// -// Attribute entries for 16-bit Thumb instructions like ADD (3) -// -#define ATTR_SET_16_ADD3(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_IT, r1:R3_0, r2:R3_3, r3:R3_6} - -// -// Attribute entries for 16-bit Thumb instructions like ADD (4) -// -#define ATTR_SET_16_ADD4(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_0H7, r2:R4_3H6} - -// -// Attribute entries for 16-bit Thumb instructions like ADD (5) -// -#define ATTR_SET_16_ADD5(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_8, r2:R_PC, cs:CS_U_8_0x4} - -// -// Attribute entries for 16-bit Thumb instructions like ADD (6) -// -#define ATTR_SET_16_ADD6(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_8, r2:R_SP, cs:CS_U_8_0x4} - -// -// Attribute entries for 16-bit Thumb instructions like ADD (7) -// -#define ATTR_SET_16_ADD7(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R_SP, cs:CS_U_7_0x4} - -// -// Attribute entries for 16-bit Thumb instructions like ASR (1) -// -#define ATTR_SET_16_ASR1(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SS) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_IT, r1:R3_0, r2:R3_3, cs:CS_U_5_6, ss:_SS} - -// -// Attribute entries for 16-bit Thumb instructions like ASR (2) -// -#define ATTR_SET_16_ASR2(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SS) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_IT, r1:R3_0, r2:R3_3, ss:_SS} - -// -// Attribute entries for 16-bit Thumb instructions like MOV (2) -// -#define ATTR_SET_16_MOV2(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_IT, r1:R3_0, r2:R3_3, cs:CS_U_5_6, ss:SS_LSL} - -// -// Attribute entries for 16-bit Thumb instructions like CMP (1) -// -#define ATTR_SET_16_CMP1(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_I, r1:R3_8, cs:CS_U_8_0} - -// -// Attribute entries for 16-bit Thumb instructions like CMP (2) -// -#define ATTR_SET_16_CMP2(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_I, r1:R3_0, r2:R3_3} - -// -// Attribute entries for 16-bit Thumb instructions like CMP (3) -// -#define ATTR_SET_16_CMP3(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_I, r1:R4_0H7, r2:R4_3H6} - -// -// Attribute entries for 16-bit Thumb instructions like B (1) -// -#define ATTR_SET_16_B1(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_T, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, cond:CO_8, ts:TC_S8} - -// -// Attribute entries for 16-bit Thumb instructions like B (2) -// -#define ATTR_SET_16_B2(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_T, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, ts:TC_S11} - -// -// Attribute entries for 16-bit Thumb instructions like BLX (2) -// -#define ATTR_SET_16_BLX2(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_3H6} - -// -// Attribute entries for 16-bit Thumb instructions like SXTH -// -#define ATTR_SET_16_SXTH(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R3_0, r2:R3_3} - -// -// Attribute entries for 16-bit Thumb instructions like BKPT -// -#define ATTR_SET_16_BKPT(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_XIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cs:CS_U_8_0} - -// -// Attribute entries for 16-bit Thumb instructions like SETEND -// -#define ATTR_SET_16_SETEND(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_ENDIAN, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cs:CS_U_1_3} - -// -// Attribute entries for 16-bit Thumb instructions like CPS -// -#define ATTR_SET_16_CPS(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_FLAGS_OPT_MODE, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, imod:IS_4, aif:AIF_0} - -// -// Attribute entries for 16-bit Thumb instructions like CBNZ -// -#define ATTR_SET_16_CBNZ(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_T, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R3_0, ts:TC_U9_7_3} - -// -// Attribute entries for 16-bit Thumb instructions like LDMIA -// -#define ATTR_SET_16_LDMIA(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _RLIST, _INC, _UA45, _UA67) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_RLIST, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_8, wb:WB_1_NB, rList:_RLIST, incDec:_INC, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 16-bit Thumb instructions like LDR (1) -// -#define ATTR_SET_16_LDR1(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_0, r2:R3_3, cs:CS_U_5_6_SZ, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 16-bit Thumb instructions like LDR (2) -// -#define ATTR_SET_16_LDR2(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_R3, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_0, r2:R3_3, r3:R3_6, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 16-bit Thumb instructions like LDR (3) -// -#define ATTR_SET_16_LDR3(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_8, r2:R_PC, cs:CS_U_8_0_SZ, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 16-bit Thumb instructions like LDR (4) -// -#define ATTR_SET_16_LDR4(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_8, r2:R_SP, cs:CS_U_8_0_SZ, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 16-bit Thumb instructions like POP -// -#define ATTR_SET_16_POP(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _RLIST, _INC, _UA45, _UA67) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_RLIST, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R_SP, pi:PI_1, wb:WB_1, rList:_RLIST, incDec:_INC, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 16-bit Thumb instructions like STMIA -// -#define ATTR_SET_16_STMIA(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _RLIST, _INC, _UA45, _UA67) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_R1_RLIST_T, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R3_8, pi:PI_1, wb:WB_1, rList:_RLIST, incDec:_INC, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 16-bit Thumb instructions like IT -// -#define ATTR_SET_16_IT(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_ITC, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, cs:CS_U_4_4, it:1} - -// -// Attribute entries for 16-bit Thumb instructions like NOP -// -#define ATTR_SET_16_NOP(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_NONE, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR} - -// -// Attribute entries for 16-bit Thumb instructions like BL_H10 -// -#define ATTR_SET_16_BL_H10(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cs:CS_S_11_0S12} - -// -// Attribute entries for 16-bit Thumb instructions like BL_H11 -// -#define ATTR_SET_16_BL_H11(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT16_##_NAME] = {opcode:_OPCODE, format:FMT_UIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cs:CS_U_11_0S1} - -// -// Attribute entry for undecoded 16-bit Thumb instruction -// -#define ATTR_SET_16_UNDECODED(_NAME) \ - [TT16_##_NAME] = {type:ARM_IT_LAST} - -#endif - diff --git a/simulators/ovp/armmModel/armAttributeEntriesThumb32.h b/simulators/ovp/armmModel/armAttributeEntriesThumb32.h deleted file mode 100644 index 4420b7e2..00000000 --- a/simulators/ovp/armmModel/armAttributeEntriesThumb32.h +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_ATTRIBUTE_ENTRIES_THUMB32_H -#define ARM_ATTRIBUTE_ENTRIES_THUMB32_H - -#include "armDisassembleFormats.h" - -// -// Attribute entries for 32-bit Thumb instructions like AND -// -#define ATTR_SET_32_AND(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_IMM] = {opcode:_OPCODE, format:FMT_R1_R2_UIMM, type:ARM_IT_##_NAME##_IMM, support:_SUPPORT, isar:_ISAR, f:SF_20_V, r1:R4_8, r2:R4_16, r3:0, cs:CS_MI, ss:0 }, \ - [TT32_##_NAME##_RM_SHFT_IMM] = {opcode:_OPCODE, format:FMT_R1_R2_R3_SHIFT_SIMM, type:ARM_IT_##_NAME##_RM_SHFT_IMM, support:_SUPPORT, isar:_ISAR, f:SF_20_V, r1:R4_8, r2:R4_16, r3:R4_0, cs:CS_PI5, ss:SS2_4 }, \ - [TT32_##_NAME##_RM_RRX] = {opcode:_OPCODE, format:FMT_R1_R2_R3_SHIFT, type:ARM_IT_##_NAME##_RM_RRX, support:_SUPPORT, isar:_ISAR, f:SF_20_V, r1:R4_8, r2:R4_16, r3:R4_0, cs:CS_NA, ss:SS_RRX} - -// -// Attribute entries for 32-bit Thumb instructions like TST -// -#define ATTR_SET_32_TST(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_IMM] = {opcode:_OPCODE, format:FMT_R1_UIMM, type:ARM_IT_##_NAME##_IMM, support:_SUPPORT, isar:_ISAR, f:SF_I, r1:R4_16, r2:0, cs:CS_MI, ss:0 }, \ - [TT32_##_NAME##_RM_SHFT_IMM] = {opcode:_OPCODE, format:FMT_R1_R2_SHIFT_SIMM, type:ARM_IT_##_NAME##_RM_SHFT_IMM, support:_SUPPORT, isar:_ISAR, f:SF_I, r1:R4_16, r2:R4_0, cs:CS_PI5, ss:SS2_4 }, \ - [TT32_##_NAME##_RM_RRX] = {opcode:_OPCODE, format:FMT_R1_R2_SHIFT, type:ARM_IT_##_NAME##_RM_RRX, support:_SUPPORT, isar:_ISAR, f:SF_I, r1:R4_16, r2:R4_0, cs:CS_NA, ss:SS_RRX} - -// -// Attribute entries for 32-bit Thumb instructions like MOV -// -#define ATTR_SET_32_MOV(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_IMM] = {opcode:_OPCODE, format:FMT_R1_UIMM, type:ARM_IT_##_NAME##_IMM, support:_SUPPORT, isar:_ISAR, f:SF_20_V, r1:R4_8, r2:0, cs:CS_MI, ss:0 }, \ - [TT32_##_NAME##_RM_SHFT_IMM] = {opcode:_OPCODE, format:FMT_R1_R2_SHIFT_SIMM, type:ARM_IT_##_NAME##_RM_SHFT_IMM, support:_SUPPORT, isar:_ISAR, f:SF_20_V, r1:R4_8, r2:R4_0, cs:CS_PI5, ss:SS2_4 }, \ - [TT32_##_NAME##_RM_RRX] = {opcode:_OPCODE, format:FMT_R1_R2_SHIFT, type:ARM_IT_##_NAME##_RM_RRX, support:_SUPPORT, isar:_ISAR, f:SF_20_V, r1:R4_8, r2:R4_0, cs:CS_NA, ss:SS_RRX} - -// -// Attribute entries for 32-bit Thumb instructions like PKHBT -// -#define ATTR_SET_32_PKHBT(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3_SHIFT_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, cs:CS_PI5, ss:SS2_4} - -// -// Attribute entries for 32-bit Thumb instructions like ADD (plain binary immediate) -// -#define ATTR_SET_32_ADD_PI(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_UIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, cs:CS_PI12} - -// -// Attribute entries for 32-bit Thumb instructions like MOV (plain binary immediate) -// -#define ATTR_SET_32_MOV_PI(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_UIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, cs:CS_PI16} - -// -// Attribute entries for 32-bit Thumb instructions like SSAT -// -#define ATTR_SET_32_SSAT(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_WIDTH_R2_SHIFT_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, cs:CS_PI5, ss:SS2_20, w:WS_WIDTH5M1} - -// -// Attribute entries for 32-bit Thumb instructions like SSAT16 -// -#define ATTR_SET_32_SSAT16(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_WIDTH_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, w:WS_WIDTH4M1} - -// -// Attribute entries for 32-bit Thumb instructions like USAT -// -#define ATTR_SET_32_USAT(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_WIDTH_R2_SHIFT_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, cs:CS_PI5, ss:SS2_20, w:WS_WIDTH5} - -// -// Attribute entries for 32-bit Thumb instructions like USAT16 -// -#define ATTR_SET_32_USAT16(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_WIDTH_R2, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, w:WS_WIDTH4} - -// -// Attribute entries for 32-bit Thumb instructions like SBFX -// -#define ATTR_SET_32_SBFX(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_LSB_WIDTH, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, cs:CS_PI5, w:WS_WIDTH5M1} - -// -// Attribute entries for 32-bit Thumb instructions like BFI -// -#define ATTR_SET_32_BFI(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_LSB_WIDTH, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, cs:CS_PI5, w:WS_MSB} - -// -// Attribute entries for 32-bit Thumb instructions like BFC -// -#define ATTR_SET_32_BFC(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_LSB_WIDTH, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_8, cs:CS_PI5, w:WS_MSB} - -// -// Attribute entries for 32-bit Thumb instructions like LSL -// -#define ATTR_SET_32_LSL(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_20_V, r1:R4_8, r2:R4_16, r3:R4_0, ss:SS2_21} - -// -// Attribute entries for 32-bit Thumb instructions like SXTAH -// -#define ATTR_SET_32_SXTAH(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3_SHIFT_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, cs:CS_U_2_4x8, ss:SS_ROR} - -// -// Attribute entries for 32-bit Thumb instructions like SXTH -// -#define ATTR_SET_32_SXTH(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_SHIFT_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_0, cs:CS_U_2_4x8, ss:SS_ROR} - -// -// Attribute entries for 32-bit Thumb parallel add/subtract instructions -// -#define ATTR_SET_32_PAS(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_S##_NAME] = {opcode:"s" _OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_S##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_Q##_NAME] = {opcode:"q" _OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_Q##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_SH##_NAME] = {opcode:"sh"_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_SH##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_U##_NAME] = {opcode:"u" _OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_U##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_UQ##_NAME] = {opcode:"uq"_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_UQ##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_UH##_NAME] = {opcode:"uh"_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_UH##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like QADD -// -#define ATTR_SET_32_QADD(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_0, r3:R4_16} - -// -// Attribute entries for 32-bit Thumb instructions like CLZ -// -#define ATTR_SET_32_CLZ(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like SEL -// -#define ATTR_SET_32_SEL(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like MLA -// -#define ATTR_SET_32_MLA(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12} - -// -// Attribute entries for 32-bit Thumb instructions like SMLAL -// -#define ATTR_SET_32_SMLAL(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_8, r3:R4_16, r4:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like MUL -// -#define ATTR_SET_32_MUL(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like SMLA -// -#define ATTR_SET_32_SMLA_XY(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##BB] = {opcode:_OPCODE"bb", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##BB, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12}, \ - [TT32_##_NAME##BT] = {opcode:_OPCODE"bt", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##BT, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12}, \ - [TT32_##_NAME##TB] = {opcode:_OPCODE"tb", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##TB, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12}, \ - [TT32_##_NAME##TT] = {opcode:_OPCODE"tt", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##TT, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12} - -// -// Attribute entries for 32-bit Thumb instructions like SMUL -// -#define ATTR_SET_32_SMUL_XY(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##BB] = {opcode:_OPCODE"bb", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##BB, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_##_NAME##BT] = {opcode:_OPCODE"bt", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##BT, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_##_NAME##TB] = {opcode:_OPCODE"tb", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##TB, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_##_NAME##TT] = {opcode:_OPCODE"tt", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##TT, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like SMLAL -// -#define ATTR_SET_32_SMLAL_XY(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##BB] = {opcode:_OPCODE"bb", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##BB, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_8, r3:R4_16, r4:R4_0}, \ - [TT32_##_NAME##BT] = {opcode:_OPCODE"bt", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##BT, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_8, r3:R4_16, r4:R4_0}, \ - [TT32_##_NAME##TB] = {opcode:_OPCODE"tb", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##TB, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_8, r3:R4_16, r4:R4_0}, \ - [TT32_##_NAME##TT] = {opcode:_OPCODE"tt", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##TT, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_8, r3:R4_16, r4:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like SMLAD -// -#define ATTR_SET_32_SMLAD(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12}, \ - [TT32_##_NAME##X] = {opcode:_OPCODE"x", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##X, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12} - -// -// Attribute entries for 32-bit Thumb instructions like SMUAD -// -#define ATTR_SET_32_SMUAD(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_##_NAME##X] = {opcode:_OPCODE"x", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##X, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0} - -// -// Attribute entries for DSP instructions like SMLAW -// -#define ATTR_SET_32_SMLAW(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##B] = {opcode:_OPCODE"b", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##B, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12}, \ - [TT32_##_NAME##T] = {opcode:_OPCODE"t", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##T, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12} - -// -// Attribute entries for DSP instructions like SMULW -// -#define ATTR_SET_32_SMULW(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##B] = {opcode:_OPCODE"b", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##B, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_##_NAME##T] = {opcode:_OPCODE"t", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##T, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0} - -// -// Attribute entries for instructions like SMMLA -// -#define ATTR_SET_32_SMMLA(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12}, \ - [TT32_##_NAME##R] = {opcode:_OPCODE"r", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##R, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0, r4:R4_12} - -// -// Attribute entries for instructions like SMMUL -// -#define ATTR_SET_32_SMMUL(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0}, \ - [TT32_##_NAME##R] = {opcode:_OPCODE"r", format:FMT_R1_R2_R3, type:ARM_IT_##_NAME##R, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_16, r3:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like SMLALD -// -#define ATTR_SET_32_SMLALD(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_8, r3:R4_16, r4:R4_0}, \ - [TT32_##_NAME##X] = {opcode:_OPCODE"x", format:FMT_R1_R2_R3_R4, type:ARM_IT_##_NAME##X, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_8, r3:R4_16, r4:R4_0} - -// -// Attribute entries for 32-bit Thumb instructions like B (1) -// -#define ATTR_SET_32_B1(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_T, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, cond:CO_22, ts:TC_S20_T2} - -// -// Attribute entries for 32-bit Thumb instructions like BL -// -#define ATTR_SET_32_BL(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_T, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, ts:TC_S24_T2} - -// -// Attribute entries for 32-bit Thumb instructions like BLX -// -#define ATTR_SET_32_BLX(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_T, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, ts:TC_S24_T4} - -// -// Attribute entries for 32-bit Thumb instructions like BXJ -// -#define ATTR_SET_32_BXJ(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_16} - -// -// Attribute entries for 32-bit Thumb instructions like MSR -// -#define ATTR_SET_32_MSR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_SR_R1, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_16, cs:CS_U_8_0, mask:MSRMASK_10} - -// -// Attribute entries for 32-bit Thumb instructions like MRS -// -#define ATTR_SET_32_MRS(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_SR, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, cs:CS_U_8_0} - -// -// Attribute entries for 32-bit Thumb instructions like DSB -// -#define ATTR_SET_32_DSB(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_LIM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cs:CS_U_4_0} - -// -// Attribute entries for 32-bit Thumb instructions like SUBS_PC_LR -// -#define ATTR_SET_32_SUBS_PC_LR(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_SIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, f:SF_V, r1:R_PC, r2:R_LR, cs:CS_U_8_0} - -// -// Attribute entries for 32-bit Thumb instructions like CPS -// -#define ATTR_SET_32_CPS(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_FLAGS_OPT_MODE, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cs:CS_U_5_0, imod:IS_9, m:1, aif:AIF_5} - -// -// Attribute entries for 32-bit Thumb instructions like NOP -// -#define ATTR_SET_32_NOP(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_NONE, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR} - -// -// Attribute entries for 32-bit Thumb instructions like DBG -// -#define ATTR_SET_32_DBG(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_UIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cs:CS_U_4_0} - -// -// Attribute entries for 32-bit Thumb instructions like SRS -// -#define ATTR_SET_32_SRS(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _INCDEC, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_WB_UIMM, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R_SP, cs:CS_U_5_0, wb:WB_21, incDec:_INCDEC, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 32-bit Thumb instructions like RFE -// -#define ATTR_SET_32_RFE(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _INCDEC, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_WB, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_16, wb:WB_21, incDec:_INCDEC, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 32-bit Thumb instructions like LDM -// -#define ATTR_SET_32_LDM(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _INCDEC, _RLIST, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_RLIST, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_16, wb:WB_21, rList:_RLIST, incDec:_INCDEC, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 32-bit Thumb instructions like POPM -// -#define ATTR_SET_32_POPM(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _INCDEC, _RLIST, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_RLIST, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_16, wb:WB_21, rList:_RLIST, incDec:_INCDEC, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 32-bit Thumb instructions like LDRD_IMM -// -#define ATTR_SET_32_LDRD_IMM(_NAME, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R4_ADDR_R2_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r4:R4_8, cs:CS_U_8_0x4_U, sz:_SZ, xs:_XS, pi:PI_24, wb:WB_21, ua45:_UA45, ua67:_UA67, u:US_23} - -// -// Attribute entries for 32-bit Thumb instructions like LDREX -// -#define ATTR_SET_32_LDREX(_NAME, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, cs:CS_U_8_0_SZ, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67, ea:1} - -// -// Attribute entries for 32-bit Thumb instructions like LDREXB -// -#define ATTR_SET_32_LDREXB(_NAME, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67, ea:1} - -// -// Attribute entries for 32-bit Thumb instructions like LDREXD -// -#define ATTR_SET_32_LDREXD(_NAME, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R4_ADDR_R2_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r4:R4_8, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67, ea:1} - -// -// Attribute entries for 32-bit Thumb instructions like STREX -// -#define ATTR_SET_32_STREX(_NAME, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_ADDR_R3_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_8, r2:R4_12, r3:R4_16, cs:CS_U_8_0_SZ, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67, ea:1} - -// -// Attribute entries for 32-bit Thumb instructions like STREXB -// -#define ATTR_SET_32_STREXB(_NAME, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_ADDR_R3_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_0, r2:R4_12, r3:R4_16, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67, ea:1} - -// -// Attribute entries for 32-bit Thumb instructions like STREXD -// -#define ATTR_SET_32_STREXD(_NAME, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_R4_ADDR_R3_SIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_0, r2:R4_12, r3:R4_16, r4:R4_8, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67, ea:1} - -// -// Attribute entries for 32-bit Thumb instructions like TBB -// -#define ATTR_SET_32_TBB(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:ADDR_R1_R2_SZSHIFT, type:ARM_IT_##_TYPE, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:R4_0, sz:_SZ, xs:_XS, ua45:_UA45, ua67:_UA67} - -// -// Attribute entries for 32-bit Thumb instructions like LDR -// -#define ATTR_SET_32_LDR(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME##_IMM1] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_TYPE##_IMM, support:_SUPPORT, isar:ARM_ISAR_NA, r1:R4_12, r2:R4_16, r3:0, cs:CS_U_12_0, ss:0, sz:_SZ, xs:_XS, tl:0, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:0 }, \ - [TT32_##_NAME##_IMM2] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_TYPE##_IMM, support:_SUPPORT, isar:ARM_ISAR_NA, r1:R4_12, r2:R4_16, r3:0, cs:CS_U_8_0_U, ss:0, sz:_SZ, xs:_XS, tl:0, pi:PI_10, wb:WB_8, ua45:_UA45, ua67:_UA67, u:US_9 }, \ - [TT32_##_NAME##_IMM3] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_TYPE##_IMM, support:_SUPPORT, isar:ARM_ISAR_NA, r1:R4_12, r2:R4_16, r3:0, cs:CS_U_12_0_U, ss:0, sz:_SZ, xs:_XS, tl:0, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:US_23}, \ - [TT32_##_NAME##_RM] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_R3, type:ARM_IT_##_TYPE##_RM, support:_SUPPORT, isar:ARM_ISAR_NA, r1:R4_12, r2:R4_16, r3:R4_0, cs:0, ss:0, sz:_SZ, xs:_XS, tl:0, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:0 }, \ - [TT32_##_NAME##_RM_SHFT_IMM] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_R3_SHIFT_SIMM, type:ARM_IT_##_TYPE##_RM_SHFT_IMM, support:_SUPPORT, isar:ARM_ISAR_NA, r1:R4_12, r2:R4_16, r3:R4_0, cs:CS_U_2_4, ss:SS_LSL, sz:_SZ, xs:_XS, tl:0, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:0 }, \ - [TT32_##_NAME##T_IMM] = {opcode:_OPCODE, format:FMT_R1_ADDR_R2_SIMM, type:ARM_IT_##_TYPE##T_IMM, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r3:0, cs:CS_U_8_0_U, ss:0, sz:_SZ, xs:_XS, tl:1, pi:PI_10, wb:WB_8, ua45:_UA45, ua67:_UA67, u:US_9 } - -// -// Attribute entries for 32-bit Thumb instructions like PLD -// -#define ATTR_SET_32_PLD(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE, _SZ, _XS, _UA45, _UA67) \ - [TT32_##_NAME##_IMM1] = {opcode:_OPCODE, format:FMT_ADDR_R1_SIMM, type:ARM_IT_##_TYPE##_IMM, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:0, cs:CS_U_12_0, ss:0, sz:_SZ, xs:_XS, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:0 }, \ - [TT32_##_NAME##_IMM2] = {opcode:_OPCODE, format:FMT_ADDR_R1_SIMM, type:ARM_IT_##_TYPE##_IMM, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:0, cs:CS_U_8_0_U, ss:0, sz:_SZ, xs:_XS, pi:PI_10, wb:WB_8, ua45:_UA45, ua67:_UA67, u:US_9 }, \ - [TT32_##_NAME##_IMM3] = {opcode:_OPCODE, format:FMT_ADDR_R1_SIMM, type:ARM_IT_##_TYPE##_IMM, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:0, cs:CS_U_12_0_U, ss:0, sz:_SZ, xs:_XS, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:US_23}, \ - [TT32_##_NAME##_RM] = {opcode:_OPCODE, format:FMT_ADDR_R1_R2, type:ARM_IT_##_TYPE##_RM, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:R4_0, cs:0, ss:0, sz:_SZ, xs:_XS, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:0 }, \ - [TT32_##_NAME##_RM_SHFT_IMM] = {opcode:_OPCODE, format:FMT_ADDR_R1_R2_SHIFT_SIMM, type:ARM_IT_##_TYPE##_RM_SHFT_IMM, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:R4_0, cs:CS_U_2_4, ss:SS_LSL, sz:_SZ, xs:_XS, pi:0, wb:0, ua45:_UA45, ua67:_UA67, u:0 } - -// -// Attribute entries for 32-bit Thumb instructions like UHINTH -// -#define ATTR_SET_32_UHINTH(_NAME, _TYPE, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_NONE, type:ARM_IT_NOP, support:_SUPPORT, isar:_ISAR} - -// -// Attribute entries for 32-bit Thumb undefined instructions -// -#define ATTR_SET_32_UND(_NAME, _SUPPORT, _ISAR) \ - [TT32_##_NAME] = {type:ARM_IT_LAST, support:_SUPPORT, isar:_ISAR} - -// -// Attribute entries for 32-bit Thumb instructions like CDP -// -#define ATTR_SET_32_CDP(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_CR1_CR2_CR3_COP2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cond:CO_28, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_4_20, cpOp2:1} - -// -// Attribute entries for 32-bit Thumb instructions like CDP2 -// -#define ATTR_SET_32_CDP2(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_CR1_CR2_CR3_COP2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_4_20, cpOp2:1} - -// -// Attribute entries for 32-bit Thumb instructions like LDC -// -#define ATTR_SET_32_LDC(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_IMM] = {opcode:_OPCODE, format:FMT_CPNUM_CR1_SIMM, type:ARM_IT_##_NAME##_IMM, support:_SUPPORT, isar:_ISAR, cond:CO_28, r1:R4_12, r2:R4_16, cs:CS_U_8_0x4_U, pi:PI_24, wb:WB_21, ll:1, cpNum:1, u:US_23}, \ - [TT32_##_NAME##_UNINDEXED] = {opcode:_OPCODE, format:FMT_CPNUM_CR1_UNINDEXED, type:ARM_IT_##_NAME##_UNINDEXED, support:_SUPPORT, isar:_ISAR, cond:CO_28, r1:R4_12, r2:R4_16, cs:CS_U_8_0, pi:PI_24, wb:WB_21, ll:1, cpNum:1, u:0 } - -// -// Attribute entries for 32-bit Thumb instructions like LDC2 -// -#define ATTR_SET_32_LDC2(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_IMM] = {opcode:_OPCODE, format:FMT_CPNUM_CR1_SIMM, type:ARM_IT_##_NAME##_IMM, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, cs:CS_U_8_0x4_U, pi:PI_24, wb:WB_21, ll:1, cpNum:1, u:US_23}, \ - [TT32_##_NAME##_UNINDEXED] = {opcode:_OPCODE, format:FMT_CPNUM_CR1_UNINDEXED, type:ARM_IT_##_NAME##_UNINDEXED, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, cs:CS_U_8_0, pi:PI_24, wb:WB_21, ll:1, cpNum:1, u:0 } - -// -// Attribute entries for 32-bit Thumb instructions like MCR -// -#define ATTR_SET_32_MCR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_R1_CR2_CR3_COP2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cond:CO_28, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_3_21, cpOp2:1} - -// -// Attribute entries for 32-bit Thumb instructions like MCR2 -// -#define ATTR_SET_32_MCR2(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_R1_CR2_CR3_COP2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_3_21, cpOp2:1} - -// -// Attribute entries for 32-bit Thumb instructions like MRC -// -#define ATTR_SET_32_MRC(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_R1F_CR2_CR3_COP2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cond:CO_28, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_3_21, cpOp2:1} - -// -// Attribute entries for 32-bit Thumb instructions like MRC2 -// -#define ATTR_SET_32_MRC2(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_R1F_CR2_CR3_COP2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_3_21, cpOp2:1} - -// -// Attribute entries for instructions like MCRR -// -#define ATTR_SET_32_MCRR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_R1_R2_CR3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, cond:CO_28, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_4_4} - -// -// Attribute entries for instructions like MCRR2 -// -#define ATTR_SET_32_MCRR2(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_CPNUM_COP1_R1_R2_CR3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r3:R4_0, cpNum:1, cpOp1:COP_4_4} - -// -// Attribute entries for instructions like VMRS -// -#define ATTR_SET_32_VMRS(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_FPSCR, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12} - -// -// Attribute entries for instructions like VMSR -// -#define ATTR_SET_32_VMSR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_FPSCR_R1, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12} - -// -// Attribute entries for instructions like VMOVRS -// -#define ATTR_SET_32_VMOVRS(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_S2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:V_16_7} - -// -// Attribute entries for instructions like VMOVSR -// -#define ATTR_SET_32_VMOVSR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_R2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:V_16_7, r2:R4_12} - -// -// Attribute entries for instructions VMOVZR -// -#define ATTR_SET_32_VMOVZR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_Z1_R2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:V_7_16, r2:R4_12, index:IDX_21} - -// -// Attribute entries for instructions VMOVRZ -// -#define ATTR_SET_32_VMOVRZ(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME ] = {opcode:_OPCODE, format:FMT_R1_Z2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:V_7_16, index:IDX_21} - -// -// Attribute entries for instructions like VMOVRRD -// -#define ATTR_SET_32_VMOVRRD(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_D3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r3:V_5_0} - -// -// Attribute entries for instructions like VMOVDRR -// -#define ATTR_SET_32_VMOVDRR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_D1_R2_R3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:V_5_0, r2:R4_12, r3:R4_16} - -// -// Attribute entries for instructions like VMOVRRSS -// -#define ATTR_SET_32_VMOVRRSS(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_R1_R2_SS3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:R4_12, r2:R4_16, r3:V_0_5} - -// -// Attribute entries for instructions like VMOVSSRR -// -#define ATTR_SET_32_VMOVSSRR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_SS1_R2_R3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, r1:V_0_5, r2:R4_12, r3:R4_16} - -// -// Attribute entries for SIMD/VFP load/store multiple instructions w/ 1 arm reg and a reg list (initial reg + number of consecutive regs) -// D/S versions -// -#define ATTR_SET_32_SDFP_LDSTM(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_D] = {opcode:_OPCODE, format:FMT_R1_SIMD_RL, type:ARM_IT_##_NAME##_D, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:V_22_12, nregs:NREG_7_1, incDec:ID_U_P, wb:WB_21, ua67:ARM_UA_DABORT}, \ - [TT32_##_NAME##_S] = {opcode:_OPCODE, format:FMT_R1_VFP_RL, type:ARM_IT_##_NAME##_S, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:V_12_22, nregs:NREG_8_0, incDec:ID_U_P, wb:WB_21, ua67:ARM_UA_DABORT} - -// -// Attribute entries for SIMD/VFP load/store instructions w/ 1 reg and 1 arm reg and an immediate -// D/S versions -// -#define ATTR_SET_32_SDFP_LDST(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_D] = {opcode:_OPCODE, format:FMT_D1_ADDR_R2_SIMM, type:ARM_IT_##_NAME##_D, support:_SUPPORT, isar:_ISAR, r1:V_22_12, r2:R4_16, cs:CS_U_8_0x4_U, u:US_23, ua67:ARM_UA_DABORT}, \ - [TT32_##_NAME##_S] = {opcode:_OPCODE, format:FMT_S1_ADDR_R2_SIMM, type:ARM_IT_##_NAME##_S, support:_SUPPORT, isar:_ISAR, r1:V_12_22, r2:R4_16, cs:CS_U_8_0x4_U, u:US_23, ua67:ARM_UA_DABORT} - -// -// Attribute entries for SIMD/VFP push/pop instructions w/ arm reg SP and a reg list (initial reg + number of consecutive regs) -// D/S versions -// -#define ATTR_SET_32_SDFP_PUSH(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME##_D] = {opcode:_OPCODE, format:FMT_SIMD_RL, type:ARM_IT_##_NAME##_D, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:V_22_12, nregs:NREG_7_1, incDec:ID_U_P_IMP, wb:WB_21, ua67:ARM_UA_DABORT}, \ - [TT32_##_NAME##_S] = {opcode:_OPCODE, format:FMT_VFP_RL, type:ARM_IT_##_NAME##_S, support:_SUPPORT, isar:_ISAR, r1:R4_16, r2:V_12_22, nregs:NREG_8_0, incDec:ID_U_P_IMP, wb:WB_21, ua67:ARM_UA_DABORT} - -// -// Attribute entries for VFP data processing instructions w/ 3 regs same length: -// -#define ATTR_SET_32_VFP_RRR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_S2_S3, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT_F32, r1:V_12_22, r2:V_16_7, r3:V_0_5} - -// -// Attribute entries for VFP data processing instructions w/ 2 regs same length: -// -#define ATTR_SET_32_VFP_RR(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_S2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT_F32, r1:V_12_22, r2:V_0_5} - -// -// Attribute entries for VFP data processing instructions w/ 1 reg and modified immediate: -// Note: immediate value 'abcdefgh' is in c (for disassembly purposes). Must still be converted to modified imm value at morph time -// -#define ATTR_SET_32_VFP_RI(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_SDFP_MI, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT_F32, r1:V_12_22, sdfpMI:SDFP_MI_VFP_S} - -// -// Attribute entries for VFP data processing instructions w/ 2 regs same length: -// S version only 2 dt1 sizes specified -// -#define ATTR_SET_32_VFP_RR_S_S2(_NAME, _SUPPORT, _ISAR, _OPCODE, _S1, _S2) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_S2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT_F##_S1, dt2:ARM_SDFPT_F##_S2, r1:V_12_22, r2:V_0_5} - -// -// Attribute entries for VFP data processing instructions w/ 1 reg and implied immediate 0.0 value -// -#define ATTR_SET_32_VFP_R0(_NAME, _SUPPORT, _ISAR, _OPCODE) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_F0, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT_F32, r1:V_12_22, r2:V_0_5} - -// -// Attribute entries for VFP data processing instructions w/ 2 regs SS: Type for dt2 specified -// -#define ATTR_SET_32_VFP_LS_T(_NAME, _SUPPORT, _ISAR, _OPCODE, _T) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_S2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT_F32, dt2:ARM_SDFPT##_T##32, r1:V_12_22, r2:V_0_5} - -// -// Attribute entries for VFP data processing instructions w/ 2 regs SS: Type for dt1 specified -// -#define ATTR_SET_32_VFP_NS_T(_NAME, _SUPPORT, _ISAR, _OPCODE, _T) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_S2, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT##_T##32, dt2:ARM_SDFPT_F32, r1:V_12_22, r2:V_0_5} - -// -// Attribute entries for VFP data processing instructions w/ 1 reg and an immediate: -// 2 ftypes with sizes specified A modifier for the constant specified -// -#define ATTR_SET_32_VFP_RI_T2C(_NAME, _SUPPORT, _ISAR, _OPCODE, _TS1, _TS2, _C) \ - [TT32_##_NAME] = {opcode:_OPCODE, format:FMT_S1_S2_UIMM, type:ARM_IT_##_NAME, support:_SUPPORT, isar:_ISAR, dt1:ARM_SDFPT##_TS1, dt2:ARM_SDFPT##_TS2, r1:V_12_22, r2:V_12_22, cs:CS_U_5_0_5M##_C} - - -#endif - diff --git a/simulators/ovp/armmModel/armBitMacros.h b/simulators/ovp/armmModel/armBitMacros.h deleted file mode 100644 index 823d200a..00000000 --- a/simulators/ovp/armmModel/armBitMacros.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_BIT_MACROS_H -#define ARM_BIT_MACROS_H - -// -// mask the argument _ARG to be _BITS bits wide -// -#define WIDTH(_BITS, _ARG) ((_ARG)&((1<<(_BITS))-1)) - -#endif diff --git a/simulators/ovp/armmModel/armBus.c b/simulators/ovp/armmModel/armBus.c deleted file mode 100644 index e77ea25f..00000000 --- a/simulators/ovp/armmModel/armBus.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -// VMI header files -#include "vmi/vmiMessage.h" -#include "vmi/vmiRt.h" - -// model header files -#include "armFunctions.h" - -static vmiBusPort busPorts[] = { - {"INSTRUCTION", vmi_BP_MASTER, vmi_DOM_CODE, 32, 1 }, - {"DATA" , vmi_BP_MASTER, vmi_DOM_DATA, 32, 0 }, - { 0 } -}; - -// -// Get the next bus port -// -VMI_BUS_PORT_SPECS_FN(armGetBusPortSpec) { - if (!prev) { - return busPorts; - } - prev++; - if (prev->name) { - return prev; - } - return 0; -} - diff --git a/simulators/ovp/armmModel/armConfig.h b/simulators/ovp/armmModel/armConfig.h deleted file mode 100644 index e79a7e7f..00000000 --- a/simulators/ovp/armmModel/armConfig.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_CONFIG_H -#define ARM_CONFIG_H - -// basic number types -#include "hostapi/impTypes.h" - -// model header files -#include "armSysRegisters.h" -#include "armTypeRefs.h" -#include "armVariant.h" - -// -// Use this to define a write mask entry in the structure below -// -#define SCS_MASK_DECL(_N) union { \ - Uns32 value32; \ - SCS_REG_STRUCT_DECL(_N) fields; \ -} _N - -// -// This structure hold configuration information about an ARM variant -// -typedef struct armConfigS { - - // name of configuration - const char *name; - - // configuration not held in system registers - armArchitecture arch :16; // specific ISA supported - Uns32 numInterrupts :16; // number of external interrupt lines - Uns32 ERG : 4; // exclusives reservation granule - Bool rotateUnaligned: 1; // rotate unaligned LDR/LDRT/SWP? - Bool align64as32 : 1; // align 64-bit load/store on 32-bit - Bool STRoffsetPC12 : 1; // STR/STM store PC with offset 12? - Uns32 priorityBitsM1 : 3; // number of priority bits, minus 1 - - // default values for system registers - struct { - SCS_REG_DECL(ICTR); - SCS_REG_DECL(ACTLR); - SCS_REG_DECL(CPUID); - SCS_REG_DECL(CPACR); - SCS_REG_DECL(SYST_CALIB); - SCS_REG_DECL(ID_PFR0); - SCS_REG_DECL(ID_PFR1); - SCS_REG_DECL(ID_DFR0); - SCS_REG_DECL(ID_AFR0); - SCS_REG_DECL(ID_MMFR0); - SCS_REG_DECL(ID_MMFR1); - SCS_REG_DECL(ID_MMFR2); - SCS_REG_DECL(ID_MMFR3); - SCS_REG_DECL(ID_ISAR0); - SCS_REG_DECL(ID_ISAR1); - SCS_REG_DECL(ID_ISAR2); - SCS_REG_DECL(ID_ISAR3); - SCS_REG_DECL(ID_ISAR4); - SCS_REG_DECL(ID_ISAR5); - SCS_REG_DECL(MVFR0); - SCS_REG_DECL(MVFR1); - SCS_REG_DECL(MPU_TYPE); - } regDefaults; - - // write masks for system registers - struct { - SCS_MASK_DECL(CPACR); - } regMasks; - -} armConfig; - -DEFINE_CS(armConfig); - -// -// This specifies configuration information for each supported variant -// -extern const struct armConfigS armConfigTable[]; - -// -// Predicates for system features -// - -// is MPU enabled? -#define MPU_ENABLED(_A) SCS_FIELD(_A, MPU_CONTROL, ENABLE) - -// is MPU unified? -#define MPU_UNIFIED(_A) (!SCS_FIELD(_A, MPU_TYPE, SEPARATE)) - -// is MPU present? -#define MPU_PRESENT(_A) SCS_FIELD(_A, MPU_TYPE, DREGION) -#define MPUS_PRESENT(_A) (MPU_PRESENT(_A) && !MPU_UNIFIED(_A)) - - -// is alignment checking enabled? -#define ALIGN_ENABLED(_A) SCS_FIELD(_A, CCR, UNALIGN_TRP) -#define DO_UNALIGNED(_A) !ALIGN_ENABLED(_A) - -// is Jazelle present? -#define JAZELLE_PRESENT(_A) ARM_SUPPORT((_A)->configInfo.arch, ARM_J) - -// get number of priority bits supported -#define PRIORITY_BITS(_A) ((_A)->configInfo.priorityBitsM1+1) - -// get number of interrupt lines -#define NUM_INTERRUPTS(_A) ((_A)->configInfo.numInterrupts) - -// is FPU present? -#define FPU_PRESENT(_A) SCS_FIELD((_A), MVFR0, A_SIMD_Registers) - -// is DSP present? -#define DSP_PRESENT(_A) (SCS_FIELD((_A), ID_ISAR3, SIMD_instrs)>2) - -#endif - diff --git a/simulators/ovp/armmModel/armDebug.h b/simulators/ovp/armmModel/armDebug.h deleted file mode 100644 index fda62474..00000000 --- a/simulators/ovp/armmModel/armDebug.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DEBUG_H -#define ARM_DEBUG_H - -// model header files -#include "armTypeRefs.h" - -// -// Add programmer's view of all system registers -// -void armAddSysRegistersView(armP arm, vmiViewObjectP processorObject); - -#endif diff --git a/simulators/ovp/armmModel/armDecode.h b/simulators/ovp/armmModel/armDecode.h deleted file mode 100644 index be88ac5a..00000000 --- a/simulators/ovp/armmModel/armDecode.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DECODE_H -#define ARM_DECODE_H - -// basic number types -#include "hostapi/impTypes.h" - -// model header files -#include "armDecodeTypes.h" -#include "armTypeRefs.h" - -// -// Decode the instruction at the passed address. The 'info' structure is filled -// with details of the instruction. -// -void armDecode(armP arm, Uns32 thisPC, armInstructionInfoP info); - -// -// Return the size of the instruction at the passed address and the mode -// -Uns32 armGetInstructionSizeMode(armP arm, Uns32 thisPC, Bool isThumb); - -// -// Return the size of the instruction at the passed address -// -Uns32 armGetInstructionSize(armP arm, Uns32 thisPC); - -#endif - diff --git a/simulators/ovp/armmModel/armDecodeEntriesThumb16.h b/simulators/ovp/armmModel/armDecodeEntriesThumb16.h deleted file mode 100644 index a5f040fa..00000000 --- a/simulators/ovp/armmModel/armDecodeEntriesThumb16.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DECODE_ENTRIES_THUMB16_H -#define ARM_DECODE_ENTRIES_THUMB16_H - -// VMI header files -#include "vmi/vmiDecode.h" - -// -// This macro adds a decode table entry for a 16-bit Thumb instruction class -// -#define DECODE_TT16(_PRIORITY, _NAME, _PATTERN) \ - {type:TT16_##_NAME, priority:_PRIORITY, name:#_NAME"_T", pattern:_PATTERN} - -// -// Decode entries for 16-bit Thumb instructions like ADC -// -#define DECODE_SET_16_ADC(_NAME, _OP) \ - DECODE_TT16(1, _NAME, "|"_OP"|...|...|") - -// -// Decode entries for 16-bit Thumb instructions like ADD (1) -// -#define DECODE_SET_16_ADD1(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|"_OP"|...|...|...|") - -// -// Decode entries for 16-bit Thumb instructions like ADD (2) -// -#define DECODE_SET_16_ADD2(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|"_OP"|...|........|") - -// -// Decode entries for 16-bit Thumb instructions like ADD (4) -// -#define DECODE_SET_16_ADD4(_NAME, _OP) \ - DECODE_TT16(1, _NAME, "|"_OP"|...|...|") - -// -// Decode entries for 16-bit Thumb instructions like ADD (7) -// -#define DECODE_SET_16_ADD7(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|"_OP"|.......|") - -// -// Decode entries for 16-bit Thumb instructions like ASR (1) -// -#define DECODE_SET_16_ASR1(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|"_OP"|.....|...|...|") - -// -// Decode entries for 16-bit Thumb instructions like B (1) -// -#define DECODE_SET_16_B1(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|1101|" _OP "|........|") - -// -// Decode entries for 16-bit Thumb instructions like B (2) -// -#define DECODE_SET_16_B2(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|111|" _OP "...........|") - -// -// Decode entries for 16-bit Thumb instructions like BLX (2) -// -#define DECODE_SET_16_BLX2(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|"_OP"|....|...|") - -// -// Decode entries for undefined 16-bit Thumb instructions like SWI -// -#define DECODE_SET_16_SWI(_NAME, _OP) \ - DECODE_TT16(1, _NAME, "|1101|" _OP "|........|") - -// -// Decode entries for 16-bit Thumb instructions like BKPT -// -#define DECODE_SET_16_BKPT(_NAME, _OP) \ - DECODE_TT16(1, _NAME, "1011|"_OP"|.....|") - -// -// Decode entries for 16-bit Thumb instructions like POP -// -#define DECODE_SET_16_POP(_NAME, _OP) \ - DECODE_TT16(0, _NAME, "|"_OP"|.|........|") - -// -// Decode entries for 16-bit Thumb instructions like IT -// -#define DECODE_SET_16_IT(_NAME, _OP1, _OP2) \ - DECODE_TT16(0, _NAME, "|1011|1111|" _OP1 "|" _OP2 "|") - -// -// Decode entries for 16-bit Thumb hint instructions like NOP -// -#define DECODE_SET_16_HINT1(_NAME, _OP1, _OP2) \ - DECODE_TT16(1, _NAME, "|1011|1111|" _OP1 "|" _OP2 "|") - -// -// Decode entries for 16-bit Thumb hint instructions like YIELD -// -#define DECODE_SET_16_HINT2(_NAME, _OP1, _OP2) \ - DECODE_TT16(2, _NAME, "|1011|1111|" _OP1 "|" _OP2 "|") - -#endif - diff --git a/simulators/ovp/armmModel/armDecodeEntriesThumb32.h b/simulators/ovp/armmModel/armDecodeEntriesThumb32.h deleted file mode 100644 index 44fba36a..00000000 --- a/simulators/ovp/armmModel/armDecodeEntriesThumb32.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DECODE_ENTRIES_THUMB32_H -#define ARM_DECODE_ENTRIES_THUMB32_H - -// VMI header files -#include "vmi/vmiDecode.h" - -// -// This macro adds a decode table entry for a 32-bit Thumb instruction class -// -#define DECODE_TT32(_PRIORITY, _NAME, _PATTERN) \ - {type:TT32_##_NAME, priority:_PRIORITY, name:#_NAME"_T", pattern:_PATTERN} - -// -// This macro adds an undefined instruction decode table entry for a 32-bit Thumb instruction class -// -#define DECODE_LAST(_PRIORITY, _PATTERN) \ - {type:TT_LAST, priority:_PRIORITY, name:"LAST_T", pattern:_PATTERN} - -// -// Decode entries for 32-bit Thumb instructions like AND -// -#define DECODE_SET_32_AND(_NAME, _OP) \ - DECODE_TT32(0, _NAME##_IMM, "|111|10.0|" _OP "|.|....|0...|....|........"), \ - DECODE_TT32(0, _NAME##_RM_SHFT_IMM, "|111|0101|" _OP "|.|....|....|....|........"), \ - DECODE_TT32(1, _NAME##_RM_RRX, "|111|0101|" _OP "|.|....|.000|....|0011....") - -// -// Decode entries for 32-bit Thumb instructions like TST -// -#define DECODE_SET_32_TST(_NAME, _OP) \ - DECODE_TT32(2, _NAME##_IMM, "|111|10.0|" _OP "|1|....|0...|1111|........"), \ - DECODE_TT32(2, _NAME##_RM_SHFT_IMM, "|111|0101|" _OP "|1|....|....|1111|........"), \ - DECODE_TT32(3, _NAME##_RM_RRX, "|111|0101|" _OP "|1|....|.000|1111|0011....") - -// -// Decode entries for 32-bit Thumb instructions like MOV -// -#define DECODE_SET_32_MOV(_NAME, _OP) \ - DECODE_TT32(2, _NAME##_IMM, "|111|10.0|" _OP "|.|1111|0...|....|........"), \ - DECODE_TT32(2, _NAME##_RM_SHFT_IMM, "|111|0101|" _OP "|.|1111|....|....|........"), \ - DECODE_TT32(3, _NAME##_RM_RRX, "|111|0101|" _OP "|.|1111|.000|....|0011....") - -// -// Decode entries for 32-bit Thumb instructions like PKHBT -// -#define DECODE_SET_32_PKHBT(_NAME, _OP) \ - DECODE_TT32(0, _NAME, "|111|01|01|0110|0|....|....|....|.." _OP "0|....") - -// -// Decode entries for 32-bit Thumb instructions like ADD (plain binary immediate) -// -#define DECODE_SET_32_ADD_PI(_NAME, _OP) \ - DECODE_TT32(0, _NAME, "|111|10|.1|" _OP "|....|0|...|....|........") - -// -// Decode entries for 32-bit Thumb instructions like ADR (plain binary immediate) -// -#define DECODE_SET_32_ADR_PI(_NAME, _OP) \ - DECODE_TT32(1, _NAME, "|111|10|.1|" _OP "|1111|0|...|....|........") - -// -// Decode entries for 32-bit Thumb instructions like SSAT16 -// -#define DECODE_SET_32_SSAT16(_NAME, _OP) \ - DECODE_TT32(1, _NAME, "|111|10|.1|" _OP "|....|0|000|....|00......") - -// -// Decode entries for 32-bit Thumb instructions like LSL -// -#define DECODE_SET_32_LSL(_NAME, _OP1, _OP2, _OP3) \ - DECODE_TT32(0, _NAME, "|111|1101|0|" _OP1 "|" _OP3 "|1111|....|" _OP2 "|....") - -// -// Decode entries for 32-bit Thumb instructions like SXTH -// -#define DECODE_SET_32_SXTH(_NAME, _OP1, _OP2, _OP3) \ - DECODE_TT32(1, _NAME, "|111|1101|0|" _OP1 "|" _OP3 "|1111|....|" _OP2 "|....") - -// -// Decode entries for parallel add/subtract instructions -// -#define DECODE_SET_32_PAS(_NAME, _OP) \ - DECODE_TT32(0, S##_NAME, "111|1101|01|" _OP "|....|1111|....|0000|....|"), \ - DECODE_TT32(0, Q##_NAME, "111|1101|01|" _OP "|....|1111|....|0001|....|"), \ - DECODE_TT32(0, SH##_NAME, "111|1101|01|" _OP "|....|1111|....|0010|....|"), \ - DECODE_TT32(0, U##_NAME, "111|1101|01|" _OP "|....|1111|....|0100|....|"), \ - DECODE_TT32(0, UQ##_NAME, "111|1101|01|" _OP "|....|1111|....|0101|....|"), \ - DECODE_TT32(0, UH##_NAME, "111|1101|01|" _OP "|....|1111|....|0110|....|") - -// -// Decode entries for 32-bit Thumb instructions like MLA -// -#define DECODE_SET_32_MLA(_NAME, _OP1, _OP2) \ - DECODE_TT32(0, _NAME, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "|....") - -// -// Decode entries for 32-bit Thumb instructions like MUL -// -#define DECODE_SET_32_MUL(_NAME, _OP1, _OP2) \ - DECODE_TT32(1, _NAME, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMLA -// -#define DECODE_SET_32_SMLA_XY(_NAME, _OP1, _OP2) \ - DECODE_TT32(0, _NAME##BB, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "00|...."), \ - DECODE_TT32(0, _NAME##BT, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "01|...."), \ - DECODE_TT32(0, _NAME##TB, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "10|...."), \ - DECODE_TT32(0, _NAME##TT, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "11|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMUL -// -#define DECODE_SET_32_SMUL_XY(_NAME, _OP1, _OP2) \ - DECODE_TT32(1, _NAME##BB, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "00|...."), \ - DECODE_TT32(1, _NAME##BT, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "01|...."), \ - DECODE_TT32(1, _NAME##TB, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "10|...."), \ - DECODE_TT32(1, _NAME##TT, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "11|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMLAD -// -#define DECODE_SET_32_SMLAD(_NAME, _OP1, _OP2) \ - DECODE_TT32(0, _NAME, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "0|...."), \ - DECODE_TT32(0, _NAME##X, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "1|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMUAD -// -#define DECODE_SET_32_SMUAD(_NAME, _OP1, _OP2) \ - DECODE_TT32(1, _NAME, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "0|...."), \ - DECODE_TT32(1, _NAME##X, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "1|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMLAW -// -#define DECODE_SET_32_SMLAW(_NAME, _OP1, _OP2) \ - DECODE_TT32(0, _NAME##B, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "0|...."), \ - DECODE_TT32(0, _NAME##T, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "1|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMULW -// -#define DECODE_SET_32_SMULW(_NAME, _OP1, _OP2) \ - DECODE_TT32(1, _NAME##B, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "0|...."), \ - DECODE_TT32(1, _NAME##T, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "1|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMMLA -// -#define DECODE_SET_32_SMMLA(_NAME, _OP1, _OP2) \ - DECODE_TT32(0, _NAME, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "0|...."), \ - DECODE_TT32(0, _NAME##R, "|111|1101|1|" _OP1 "|....|....|....|" _OP2 "1|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like SMMUL -// -#define DECODE_SET_32_SMMUL(_NAME, _OP1, _OP2) \ - DECODE_TT32(1, _NAME, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "0|...."), \ - DECODE_TT32(1, _NAME##R, "|111|1101|1|" _OP1 "|....|1111|....|" _OP2 "1|....") - -// -// Decode entries for 32-bit Thumb instructions like BFC -// -#define DECODE_SET_32_BFC(_NAME, _OP) \ - DECODE_TT32(1, _NAME, "|111|10|.1|" _OP "|1111|0|...|....|........") - -// -// Decode entries for 32-bit Thumb instructions like B (1) -// -#define DECODE_SET_32_B1(_NAME, _OP1, _OP2) \ - DECODE_TT32(0, _NAME, "|111|10|...........|1|" _OP1 "|..........." _OP2) - -// -// Decode entries for 32-bit Thumb undefined instructions -// -#define DECODE_SET_32_UNDEF(_NAME, _OP1, _OP2) \ - DECODE_TT32(1, _NAME, "|111|10|" _OP2 "|....|1|" _OP1 "|....|........") - -// -// Decode entries for 32-bit Thumb instructions like MSR -// -#define DECODE_SET_32_MSR(_NAME, _OP1, _OP2) \ - DECODE_TT32(2, _NAME, "|111|10|" _OP2 "|....|1|" _OP1 "|....|........") - -// -// Decode entries for 32-bit Thumb hint instructions like NOP -// -#define DECODE_SET_32_HINT1(_NAME, _OP1, _OP2, _OP3) \ - DECODE_TT32(3, _NAME, "|111|10|" _OP2 "|....|1|" _OP1 "|.000|" _OP3) - -// -// Decode entries for 32-bit Thumb hint instructions like YIELD -// -#define DECODE_SET_32_HINT2(_NAME, _OP1, _OP2, _OP3) \ - DECODE_TT32(4, _NAME, "|111|10|" _OP2 "|....|1|" _OP1 "|.000|" _OP3) - -// -// Decode entries for 32-bit Thumb instructions like CLREX -// -#define DECODE_SET_32_CLREX(_NAME, _OP) \ - DECODE_TT32(2, _NAME, "|111|10|0111011|....|10.0|....|" _OP "|....") - -// -// Decode entries for 32-bit Thumb instructions like SRS -// -#define DECODE_SET_32_SRS(_NAME, _OP1, _OP2) \ - DECODE_TT32(1, _NAME, "|111|0100|" _OP1 "|0|" _OP2 "|................") - -// -// Decode entries for 32-bit Thumb instructions like POPM -// -#define DECODE_SET_32_POPM(_NAME, _OP1, _OP2) \ - DECODE_TT32(2, _NAME, "|111|0100|" _OP1 "|0|" _OP2 "|................") - -// -// Decode entries for 32-bit Thumb instructions like LDRD_IMM -// -#define DECODE_SET_32_LDRD_IMM(_NAME, _OP1, _OP2, _OP3) \ - DECODE_TT32(0, _NAME, "|111|0100|" _OP1 "|1|" _OP2 "|....|........" _OP3 "....") - -// -// Decode entries for 32-bit Thumb instructions like LDREX -// -#define DECODE_SET_32_LDREX(_NAME, _OP1, _OP2, _OP3) \ - DECODE_TT32(1, _NAME, "|111|0100|" _OP1 "|1|" _OP2 "|....|........" _OP3 "....") - -// -// Decode entries for 32-bit Thumb instructions like LDR -// -#define DECODE_SET_32_LDR(_NAME, _SIGN, _SZ) \ - DECODE_TT32(0, _NAME##_IMM1, "|111|1100|" _SIGN "1|" _SZ "|1|....|....|......|......"), \ - DECODE_TT32(1, _NAME##_IMM2, "|111|1100|" _SIGN "0|" _SZ "|1|....|....|1..1..|......"), \ - DECODE_TT32(1, _NAME##_IMM2, "|111|1100|" _SIGN "0|" _SZ "|1|....|....|1100..|......"), \ - DECODE_TT32(3, _NAME##_IMM3, "|111|1100|" _SIGN "0|" _SZ "|1|1111|....|......|......"), \ - DECODE_TT32(2, _NAME##_RM, "|111|1100|" _SIGN "0|" _SZ "|1|....|....|000000|00...."), \ - DECODE_TT32(1, _NAME##_RM_SHFT_IMM, "|111|1100|" _SIGN "0|" _SZ "|1|....|....|000000|......"), \ - DECODE_TT32(1, _NAME##T_IMM, "|111|1100|" _SIGN "0|" _SZ "|1|....|....|1110..|......") - -// -// Decode entries for 32-bit Thumb instructions like STR -// -#define DECODE_SET_32_STR(_NAME, _SIGN, _SZ) \ - DECODE_TT32(0, _NAME##_IMM1, "|111|1100|" _SIGN "1|" _SZ "|0|....|....|......|......"), \ - DECODE_TT32(1, _NAME##_IMM2, "|111|1100|" _SIGN "0|" _SZ "|0|....|....|1..1..|......"), \ - DECODE_TT32(1, _NAME##_IMM2, "|111|1100|" _SIGN "0|" _SZ "|0|....|....|1100..|......"), \ - DECODE_TT32(3, _NAME##_IMM3, "|111|1100|" _SIGN "0|" _SZ "|0|1111|....|......|......"), \ - DECODE_TT32(2, _NAME##_RM, "|111|1100|" _SIGN "0|" _SZ "|0|....|....|000000|00...."), \ - DECODE_TT32(1, _NAME##_RM_SHFT_IMM, "|111|1100|" _SIGN "0|" _SZ "|0|....|....|000000|......"), \ - DECODE_TT32(1, _NAME##T_IMM, "|111|1100|" _SIGN "0|" _SZ "|0|....|....|1110..|......") - -// -// Decode entries for 32-bit Thumb instructions like PLD -// -#define DECODE_SET_32_PLD(_NAME, _SIGN, _SZ) \ - DECODE_TT32(5, _NAME##_IMM1, "|111|1100|" _SIGN "1|" _SZ "|1|....|1111|......|......"), \ - DECODE_TT32(6, _NAME##_IMM2, "|111|1100|" _SIGN "0|" _SZ "|1|....|1111|1100..|......"), \ - DECODE_TT32(8, _NAME##_IMM3, "|111|1100|" _SIGN "0|" _SZ "|1|1111|1111|......|......"), \ - DECODE_TT32(7, _NAME##_RM, "|111|1100|" _SIGN "0|" _SZ "|1|....|1111|000000|00...."), \ - DECODE_TT32(6, _NAME##_RM_SHFT_IMM, "|111|1100|" _SIGN "0|" _SZ "|1|....|1111|000000|......") - -// -// Decode entries for 32-bit Thumb instructions like UHINTH -// -#define DECODE_SET_32_UHINTH(_NAME, _SZ) \ - DECODE_TT32(4, _NAME, "|111|1100|..|" _SZ "|1|....|1111|......|......") - -// -// Decode entries for 32-bit Thumb instructions like CDP -// -#define DECODE_SET_32_CDP(_NAME) \ - DECODE_TT32(0, _NAME, "....|1110|....|....|....|....|...|0|....") - -// -// Decode entries for 32-bit Thumb instructions like CDP2 -// -#define DECODE_SET_32_CDP2(_NAME) \ - DECODE_TT32(1, _NAME, "1111|1110|....|....|....|....|...|0|....") - -// -// Decode entries for 32-bit Thumb instructions like LDC -// -#define DECODE_SET_32_LDC(_NAME, _OP) \ - DECODE_TT32(0, _NAME##_IMM, "....|110|...." _OP "|....|....|....|........"), \ - DECODE_TT32(1, _NAME##_UNINDEXED, "....|110|0..0" _OP "|....|....|....|........") - -// -// Decode entries for 32-bit Thumb instructions like LDC2 -// -#define DECODE_SET_32_LDC2(_NAME, _OP) \ - DECODE_TT32(2, _NAME##_IMM, "1111|110|...." _OP "|....|....|....|........"), \ - DECODE_TT32(3, _NAME##_UNINDEXED, "1111|110|0..0" _OP "|....|....|....|........") - -// -// Decode entries for 32-bit Thumb instructions like MCR -// -#define DECODE_SET_32_MCR(_NAME, _OP) \ - DECODE_TT32(0, _NAME, "....|1110|...|" _OP "|....|....|....|...|1|....") - -// -// Decode entries for 32-bit Thumb instructions like MCR2 -// -#define DECODE_SET_32_MCR2(_NAME, _OP) \ - DECODE_TT32(1, _NAME, "1111|1110|...|" _OP "|....|....|....|...|1|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like MCRR -// -#define DECODE_SET_32_MCRR(_NAME, _OP) \ - DECODE_TT32(4, _NAME, "....|1100010" _OP "|....|....|....|....|....") - -// -// Decode entries for 32-bit Thumb DSP instructions like MCRR2 -// -#define DECODE_SET_32_MCRR2(_NAME, _OP) \ - DECODE_TT32(5, _NAME, "1111|1100010" _OP "|....|....|....|....|....") - -// -// Decode entries for VFP/SIMD instructions like VMRS -// Note - When bit 28=1 manual states this is an undefined instruction so extra -// decode is added. Without it this decodes as MRC and gives NOCP fault. -// -#define DECODE_SET_32_VMRS(_NAME, _OPL, _OPC, _OPA, _OPB) \ - DECODE_TT32(2, _NAME, "1110|1110" _OPA _OPL "|....|....|101" _OPC "|." _OPB "1|...."), \ - DECODE_LAST(2, "1111|1110" _OPA _OPL "|....|....|101" _OPC "|." _OPB "1|....") - -// -// Decode entries for VFP instructions like VMOVRRD -// -#define DECODE_SET_32_VMOVRRD(_NAME, _OPL, _OPC, _OP) \ - DECODE_TT32(6, _NAME, "1110|1100|010" _OPL "........|101" _OPC _OP "|...."), \ - DECODE_LAST(6, "1111|1100|010" _OPL "........|101" _OPC _OP "|....") - -// -// Decode entries for SIMD/VFP load/store instructions -// -#define DECODE_SET_32_SDFP_LDST(_NAME, _OP) \ - DECODE_TT32(4, _NAME##_D, "1110|110" _OP "|....|....|1011|....|...."), \ - DECODE_TT32(4, _NAME##_S, "1110|110" _OP "|....|....|1010|....|...."), \ - DECODE_LAST(6, "1111|110" _OP "|....|....|101.|....|....") - -// -// Decode entries for SIMD/VFP PUSH/POP instructions -// -#define DECODE_SET_32_SDFP_PUSH_POP(_NAME, _OP) \ - DECODE_TT32(5, _NAME##_D, "1110|110" _OP "|1101|....|1011|....|...."), \ - DECODE_TT32(5, _NAME##_S, "1110|110" _OP "|1101|....|1010|....|....") - -// -// Decode entries for VFP instructions S version only -// -#define DECODE_SET_32_VFP_S(_NAME, _OP1, _OP2, _OP3) \ - DECODE_TT32(2, _NAME, "1110|1110|" _OP1 _OP2 "|....|1010|" _OP3 ".0|...."), \ - DECODE_LAST(3, "1111|1110|" _OP1 _OP2 "|....|1010|" _OP3 ".0|....") -#endif - diff --git a/simulators/ovp/armmModel/armDecodeThumb.h b/simulators/ovp/armmModel/armDecodeThumb.h deleted file mode 100644 index 1f56bb93..00000000 --- a/simulators/ovp/armmModel/armDecodeThumb.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DECODE_THUMB_H -#define ARM_DECODE_THUMB_H - -// basic number types -#include "hostapi/impTypes.h" - -// model header files -#include "armDecodeTypes.h" -#include "armTypeRefs.h" - -// -// Return size in bytes of Thumb instruction at the passed address -// -Uns32 armGetThumbInstructionSize(armP arm, Uns32 thisPC); - -// -// Decode the Thumb instruction at the passed address. The 'info' structure is -// filled with details of the instruction. -// -void armDecodeThumb(armP arm, Uns32 thisPC, armInstructionInfoP info); - -#endif - diff --git a/simulators/ovp/armmModel/armDecodeTypes.h b/simulators/ovp/armmModel/armDecodeTypes.h deleted file mode 100644 index a0401e6f..00000000 --- a/simulators/ovp/armmModel/armDecodeTypes.h +++ /dev/null @@ -1,762 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DECODE_TYPES_H -#define ARM_DECODE_TYPES_H - -// basic number types -#include "hostapi/impTypes.h" - -// model header files -#include "armVariant.h" - - -// -// Instruction type for an instruction with a single variant -// -#define ITYPE_SINGLE(_NAME) \ - ARM_IT_##_NAME - -// -// Instruction types for normal instructions like ADC -// -#define ITYPE_SET_ADC(_NAME) \ - ARM_IT_##_NAME##_IMM, \ - ARM_IT_##_NAME##_RM, \ - ARM_IT_##_NAME##_RM_SHFT_IMM, \ - ARM_IT_##_NAME##_RM_RRX, \ - ARM_IT_##_NAME##_IT, \ - ARM_IT_##_NAME##_RT - -// -// Instruction types for normal instructions like LDC -// -#define ITYPE_SET_LDC(_NAME) \ - ARM_IT_##_NAME##_IMM, \ - ARM_IT_##_NAME##_UNINDEXED - -// -// Instruction types for normal instructions like LDR -// -#define ITYPE_SET_LDR(_NAME) \ - ARM_IT_##_NAME##_IMM, \ - ARM_IT_##_NAME##_RM, \ - ARM_IT_##_NAME##_RM_SHFT_IMM - -// -// Instruction types for normal instructions like LDRH -// -#define ITYPE_SET_LDRH(_NAME) \ - ARM_IT_##_NAME##_IMM, \ - ARM_IT_##_NAME##_RM \ - -// -// Instruction types for normal instructions like MOV -// -#define ITYPE_SET_MOV(_NAME) \ - ARM_IT_##_NAME##_IMM, \ - ARM_IT_##_NAME##_RM, \ - ARM_IT_##_NAME##_RM_SHFT_IMM, \ - ARM_IT_##_NAME##_RM_SHFT_RS, \ - ARM_IT_##_NAME##_RM_RRX, \ - ARM_IT_##_NAME##_RM_SHFT_RST - -// -// Instruction types for DSP instructions like SMLA -// -#define ITYPE_SET_SMLA_XY(_NAME) \ - ARM_IT_##_NAME##BB, \ - ARM_IT_##_NAME##BT, \ - ARM_IT_##_NAME##TB, \ - ARM_IT_##_NAME##TT - -// -// Instruction types for DSP instructions like SMLAW -// -#define ITYPE_SET_SMLAW_Y(_NAME) \ - ARM_IT_##_NAME##B, \ - ARM_IT_##_NAME##T - -// -// Instruction types for normal instructions like PLD -// -#define ITYPE_SET_PLD(_NAME) \ - ARM_IT_##_NAME##_IMM, \ - ARM_IT_##_NAME##_RM, \ - ARM_IT_##_NAME##_RM_SHFT_IMM - -// -// Instruction types for parallel add/subtract Media instructions -// -#define ITYPE_SET_PAS(_NAME) \ - ARM_IT_S##_NAME, \ - ARM_IT_Q##_NAME, \ - ARM_IT_SH##_NAME, \ - ARM_IT_U##_NAME, \ - ARM_IT_UQ##_NAME, \ - ARM_IT_UH##_NAME - -// -// Instruction types for Media instructions with optional argument exchange -// -#define ITYPE_MEDIA_X(_NAME) \ - ARM_IT_##_NAME, \ - ARM_IT_##_NAME##X - -// -// Instruction types for Media instructions with optional result rounding -// -#define ITYPE_MEDIA_R(_NAME) \ - ARM_IT_##_NAME, \ - ARM_IT_##_NAME##R - -// -// Instruction types for VFP instructions with D and S variants -// -#define ITYPE_VFP_DS(_NAME) \ - ARM_IT_##_NAME##_D, \ - ARM_IT_##_NAME##_S - -// -// Instruction type enumeration -// -typedef enum armInstructionTypeE { - - //////////////////////////////////////////////////////////////////////////// - // ARM INSTRUCTIONS - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - ITYPE_SET_ADC (ADC), - ITYPE_SET_ADC (ADD), - ITYPE_SET_ADC (AND), - ITYPE_SET_ADC (BIC), - ITYPE_SET_ADC (EOR), - ITYPE_SET_MOV (MOV), - ITYPE_SET_ADC (MUL), - ITYPE_SET_MOV (MVN), - ITYPE_SET_MOV (NEG), - ITYPE_SET_ADC (ORN), - ITYPE_SET_ADC (ORR), - ITYPE_SET_ADC (RSB), - ITYPE_SET_ADC (RSC), - ITYPE_SET_ADC (SBC), - ITYPE_SET_ADC (SUB), - - // ARMv6T2 move instructions - ITYPE_SINGLE (MOVT), - ITYPE_SINGLE (MOVW), - - // multiply instructions - ITYPE_SINGLE (MLA ), - ITYPE_SINGLE (MLS ), - ITYPE_SINGLE (MUL ), - ITYPE_SINGLE (SMLAL), - ITYPE_SINGLE (SMULL), - ITYPE_SINGLE (UMAAL), - ITYPE_SINGLE (UMLAL), - ITYPE_SINGLE (UMULL), - - // compare instructions - ITYPE_SET_ADC (CMN), - ITYPE_SET_ADC (CMP), - ITYPE_SET_ADC (TEQ), - ITYPE_SET_ADC (TST), - - // branch instructions - ITYPE_SINGLE (B ), - ITYPE_SINGLE (BL ), - ITYPE_SINGLE (BLX2), - ITYPE_SINGLE (BX ), - - // miscellaneous instructions - ITYPE_SINGLE (BKPT), - ITYPE_SINGLE (CLZ ), - ITYPE_SINGLE (SWI ), - - // load and store instructions - ITYPE_SET_LDR (LDR ), - ITYPE_SET_LDR (LDRB ), - ITYPE_SET_LDR (LDRBT), - ITYPE_SET_LDRH (LDRH ), - ITYPE_SET_LDRH (LDRSB), - ITYPE_SET_LDRH (LDRSH), - ITYPE_SET_LDR (LDRT ), - ITYPE_SET_LDR (STR ), - ITYPE_SET_LDR (STRB ), - ITYPE_SET_LDR (STRBT), - ITYPE_SET_LDRH (STRH ), - ITYPE_SET_LDR (STRT ), - - // load and store multiple instructions - ITYPE_SINGLE (LDM1), - ITYPE_SINGLE (STM1), - - // ARMv6T2 load and store instructions - ITYPE_SET_LDRH (LDRHT ), - ITYPE_SET_LDRH (LDRSBT), - ITYPE_SET_LDRH (LDRSHT), - ITYPE_SET_LDRH (STRHT ), - - // synchronization primitives - ITYPE_SINGLE (LDREX ), - ITYPE_SINGLE (LDREXB), - ITYPE_SINGLE (LDREXH), - ITYPE_SINGLE (STREX ), - ITYPE_SINGLE (STREXB), - ITYPE_SINGLE (STREXH), - - // coprocessor instructions - ITYPE_SINGLE (CDP ), - ITYPE_SINGLE (CDP2), - ITYPE_SET_LDC (LDC ), - ITYPE_SET_LDC (LDC2), - ITYPE_SINGLE (MCR ), - ITYPE_SINGLE (MCR2), - ITYPE_SINGLE (MRC ), - ITYPE_SINGLE (MRC2), - ITYPE_SET_LDC (STC ), - ITYPE_SET_LDC (STC2), - - // status register access instructions - ITYPE_SINGLE (MRS), - ITYPE_SINGLE (MSR), - - // hints - ITYPE_SINGLE (NOP ), - ITYPE_SINGLE (YIELD), - ITYPE_SINGLE (WFE ), - ITYPE_SINGLE (WFI ), - ITYPE_SINGLE (SEV ), - ITYPE_SINGLE (DBG ), - - // ARMv6 miscellaneous instructions - ITYPE_SINGLE (CPS ), - ITYPE_SINGLE (CLREX ), - ITYPE_SINGLE (DSB ), - ITYPE_SINGLE (ISB ), - - // ARMv7 hint instructions - ITYPE_SET_PLD (PLD), - ITYPE_SET_PLD (PLI), - ITYPE_SINGLE (DMB), - - //////////////////////////////////////////////////////////////////////////// - // DSP INSTRUCTIONS - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - ITYPE_SINGLE (QADD ), - ITYPE_SINGLE (QDADD), - ITYPE_SINGLE (QDSUB), - ITYPE_SINGLE (QSUB ), - - // multiply instructions - ITYPE_SET_SMLA_XY (SMLA ), - ITYPE_SET_SMLA_XY (SMLAL), - ITYPE_SET_SMLAW_Y (SMLAW), - ITYPE_SET_SMLA_XY (SMUL ), - ITYPE_SET_SMLAW_Y (SMULW), - - // load and store instructions - ITYPE_SET_LDRH (LDRD), - ITYPE_SET_LDRH (STRD), - - // coprocessor instructions - ITYPE_SINGLE (MCRR ), - ITYPE_SINGLE (MCRR2), - ITYPE_SINGLE (MRRC ), - ITYPE_SINGLE (MRRC2), - - //////////////////////////////////////////////////////////////////////////// - // MEDIA INSTRUCTIONS - //////////////////////////////////////////////////////////////////////////// - - // basic instructions - ITYPE_SINGLE (USAD8 ), - ITYPE_SINGLE (USADA8), - ITYPE_SINGLE (SBFX ), - ITYPE_SINGLE (BFC ), - ITYPE_SINGLE (BFI ), - ITYPE_SINGLE (UBFX ), - - // parallel add/subtract instructions - ITYPE_SET_PAS (ADD16), - ITYPE_SET_PAS (ASX ), - ITYPE_SET_PAS (SAX ), - ITYPE_SET_PAS (SUB16), - ITYPE_SET_PAS (ADD8 ), - ITYPE_SET_PAS (SUB8 ), - - // packing, unpacking, saturation and reversal instructions - ITYPE_SINGLE (PKHBT ), - ITYPE_SINGLE (PKHTB ), - ITYPE_SINGLE (SSAT ), - ITYPE_SINGLE (SSAT16 ), - ITYPE_SINGLE (USAT ), - ITYPE_SINGLE (USAT16 ), - ITYPE_SINGLE (SXTAB ), - ITYPE_SINGLE (UXTAB ), - ITYPE_SINGLE (SXTAB16), - ITYPE_SINGLE (UXTAB16), - ITYPE_SINGLE (SXTAH ), - ITYPE_SINGLE (UXTAH ), - ITYPE_SINGLE (SXTB ), - ITYPE_SINGLE (UXTB ), - ITYPE_SINGLE (SXTB16 ), - ITYPE_SINGLE (UXTB16 ), - ITYPE_SINGLE (SXTH ), - ITYPE_SINGLE (UXTH ), - ITYPE_SINGLE (SEL ), - ITYPE_SINGLE (REV ), - ITYPE_SINGLE (REV16 ), - ITYPE_SINGLE (RBIT ), - ITYPE_SINGLE (REVSH ), - - // signed multiply instructions - ITYPE_MEDIA_X (SMLAD ), - ITYPE_MEDIA_X (SMUAD ), - ITYPE_MEDIA_X (SMLSD ), - ITYPE_MEDIA_X (SMUSD ), - ITYPE_MEDIA_X (SMLALD), - ITYPE_MEDIA_X (SMLSLD), - ITYPE_MEDIA_R (SMMLA ), - ITYPE_MEDIA_R (SMMUL ), - ITYPE_MEDIA_R (SMMLS ), - - // VFP data processing instructions - ITYPE_SINGLE (VMLA_VFP), - ITYPE_SINGLE (VMLS_VFP), - ITYPE_SINGLE (VNMLS_VFP), - ITYPE_SINGLE (VNMLA_VFP), - ITYPE_SINGLE (VMUL_VFP), - ITYPE_SINGLE (VNMUL_VFP), - ITYPE_SINGLE (VADD_VFP), - ITYPE_SINGLE (VSUB_VFP), - ITYPE_SINGLE (VDIV_VFP), - ITYPE_SINGLE (VFMA_VFP), - ITYPE_SINGLE (VFMS_VFP), - ITYPE_SINGLE (VFNMS_VFP), - ITYPE_SINGLE (VFNMA_VFP), - ITYPE_SINGLE (VMOVI_VFP), - ITYPE_SINGLE (VMOVR_VFP), - ITYPE_SINGLE (VABS_VFP), - ITYPE_SINGLE (VNEG_VFP), - ITYPE_SINGLE (VSQRT_VFP), - ITYPE_SINGLE (VCVTBFH_VFP), - ITYPE_SINGLE (VCVTTFH_VFP), - ITYPE_SINGLE (VCVTBHF_VFP), - ITYPE_SINGLE (VCVTTHF_VFP), - ITYPE_SINGLE (VCMP_VFP), - ITYPE_SINGLE (VCMPE_VFP), - ITYPE_SINGLE (VCMP0_VFP), - ITYPE_SINGLE (VCMPE0_VFP), - ITYPE_SINGLE (VCVTFU_VFP), - ITYPE_SINGLE (VCVTFS_VFP), - ITYPE_SINGLE (VCVTFXUH_VFP), - ITYPE_SINGLE (VCVTFXUW_VFP), - ITYPE_SINGLE (VCVTFXSH_VFP), - ITYPE_SINGLE (VCVTFXSW_VFP), - ITYPE_SINGLE (VCVTUF_VFP), - ITYPE_SINGLE (VCVTRUF_VFP), - ITYPE_SINGLE (VCVTSF_VFP), - ITYPE_SINGLE (VCVTRSF_VFP), - ITYPE_SINGLE (VCVTXFSH_VFP), - ITYPE_SINGLE (VCVTXFSW_VFP), - ITYPE_SINGLE (VCVTXFUH_VFP), - ITYPE_SINGLE (VCVTXFUW_VFP), - - // Extension register load/store instructions - ITYPE_VFP_DS (VSTMIA), - ITYPE_VFP_DS (VSTMIAW), - ITYPE_VFP_DS (VSTR), - ITYPE_VFP_DS (VSTMDBW), - ITYPE_VFP_DS (VPUSH), - ITYPE_VFP_DS (VLDMIA), - ITYPE_VFP_DS (VLDMIAW), - ITYPE_VFP_DS (VPOP), - ITYPE_VFP_DS (VLDR), - ITYPE_VFP_DS (VLDMDBW), - - // 8, 16 and 32-bit transfer instructions between ARM core regs and extension regs - ITYPE_SINGLE (VMRS), - ITYPE_SINGLE (VMSR), - ITYPE_SINGLE (VMOVRS), - ITYPE_SINGLE (VMOVSR), - ITYPE_SINGLE (VMOVZR), - ITYPE_SINGLE (VMOVRZ), - - // 64-bit transfer instructions between ARM core regs and extension regs - ITYPE_SINGLE (VMOVRRD), - ITYPE_SINGLE (VMOVDRR), - ITYPE_SINGLE (VMOVRRSS), - ITYPE_SINGLE (VMOVSSRR), - - //////////////////////////////////////////////////////////////////////////// - // THUMB INSTRUCTIONS (WHEN DISTINCT FROM ARM INSTRUCTIONS) - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - ITYPE_SINGLE (ADD4), - ITYPE_SINGLE (ADD6), - ITYPE_SINGLE (ADD7), - ITYPE_SINGLE (SUB4), - ITYPE_SINGLE (MOV3), - - // address instructions - ITYPE_SINGLE (ADD_ADR), - ITYPE_SINGLE (SUB_ADR), - - // branch instructions - ITYPE_SINGLE (CBNZ), - ITYPE_SINGLE (CBZ ), - ITYPE_SINGLE (TB ), - - // divide instructions - ITYPE_SINGLE (SDIV), - ITYPE_SINGLE (UDIV), - - // KEEP LAST - ITYPE_SINGLE (LAST) - -} armInstructionType; - -// -// Condition code enumeration -// -typedef enum armConditionE { - - ARM_C_EQ, // ZF==1 - ARM_C_NE, // ZF==0 - ARM_C_CS, // CF==1 - ARM_C_CC, // CF==0 - ARM_C_MI, // NF==1 - ARM_C_PL, // NF==0 - ARM_C_VS, // VF==1 - ARM_C_VC, // VF==0 - ARM_C_HI, // (CF==1) && (ZF==0) - ARM_C_LS, // (CF==0) || (ZF==1) - ARM_C_GE, // NF==VF - ARM_C_LT, // NF!=VF - ARM_C_GT, // (ZF==0) && (NF==VF) - ARM_C_LE, // (ZF==1) || (NF!=VF) - ARM_C_AL, // always - ARM_C_NV, // never - - // KEEP LAST - ARM_C_LAST - -} armCondition; - -// -// This defines whether the instruction sets flags -// -typedef enum armSetFlagsE { - ARM_SF_0, // don't set flags - ARM_SF_V, // set flags, show in disassembly using "s" suffix - ARM_SF_I, // set flags, not shown in instruction disassembly - ARM_SF_IT, // only when not in if-then block -} armSetFlags; - -// -// This defines shift operations -// -typedef enum armShiftOpE { - ARM_SO_NA, // no shift operation - ARM_SO_LSL, // logical shift left - ARM_SO_LSR, // logical shift right - ARM_SO_ASR, // arithmetic shift right - ARM_SO_ROR, // rotate right - ARM_SO_RRX // rotate right with extend -} armShiftOp; - -// -// This defines increment/decrement actions -// -typedef enum armIncDecE { - ARM_ID_NA = 0x0, // no increment/decrement spec present - ARM_ID_D = 0x0, // decrement - ARM_ID_I = 0x1, // increment - ARM_ID_A = 0x0, // after - ARM_ID_B = 0x2, // before - ARM_ID_NS = 0x4, // not shown in disassembly - ARM_ID_P = 0x8, // increment/decrement spec present - ARM_ID_DA = ARM_ID_P | ARM_ID_D | ARM_ID_A, // decrement after - ARM_ID_IA = ARM_ID_P | ARM_ID_I | ARM_ID_A, // increment after - ARM_ID_DB = ARM_ID_P | ARM_ID_D | ARM_ID_B, // decrement before - ARM_ID_IB = ARM_ID_P | ARM_ID_I | ARM_ID_B, // increment before - ARM_ID_IAI = ARM_ID_IA | ARM_ID_NS, // IA, not shown in disassembly - ARM_ID_IBI = ARM_ID_IB | ARM_ID_NS, // IB, not shown in disassembly - ARM_ID_DAI = ARM_ID_DA | ARM_ID_NS, // DA, not shown in disassembly - ARM_ID_DBI = ARM_ID_DB | ARM_ID_NS // DB, not shown in disassembly -} armIncDec; - -// -// This defines bits in a field mask -// -typedef enum armSRFieldMaskE { - ARM_SR_C = 0x1, // control field mask bit - ARM_SR_X = 0x2, // extension field mask bit - ARM_SR_S = 0x4, // status field mask bit - ARM_SR_F = 0x8 // flags field mask bit -} armSRFieldMask; - -// -// This defines actions to be taken for unaligned memory accesses -// -typedef enum armUnalignedActionE { - ARM_UA_DABORT, // take data abort exception - ARM_UA_ROTATE, // rotate if unaligned (some ARMv4 and ARMv5 reads) - ARM_UA_ALIGN, // force alignment - ARM_UA_UNALIGNED, // allow unaligned access -} armUnalignedAction; - -// -// This specifies the effect on any interrupt flags of this instruction -// -typedef enum armFlagActionE { - ARM_FACT_NA = 0, // no flag action - ARM_FACT_BAD = 1, // (illegal value) - ARM_FACT_IE = 2, // interrupts enabled - ARM_FACT_ID = 3 // interrupts disabled -} armFlagAction; - -// -// This specifies flags affected by this instruction -// -typedef enum armFlagAffectE { - ARM_FAFF_NA = 0x0, // no flags affected - ARM_FAFF_F = 0x1, // F flag affected - ARM_FAFF_I = 0x2, // I flag affected - ARM_FAFF_A = 0x4, // A flag affected -} armFlagAffect; - -// -// This specifies system registers for MSR/MRS -// -typedef enum armSysRegIdE { - ASRID_APSR = 0, - ASRID_IAPSR = 1, - ASRID_EAPSR = 2, - ASRID_XPSR = 3, - ASRID_IPSR = 5, - ASRID_EPSR = 6, - ASRID_IEPSR = 7, - ASRID_MSP = 8, - ASRID_PSP = 9, - ASRID_PRIMASK = 16, - ASRID_BASEPRI = 17, - ASRID_BASEPRI_MAX = 18, - ASRID_FAULTMASK = 19, - ASRID_CONTROL = 20 -} armSysRegId; - -// -// This specifies bits specified by mask field of MSR -// -typedef enum armPSRBitsE { - ARM_PSRBITS_NA = 0, // no bits specified - ARM_PSRBITS_GE = 1, // GE only, no flags - ARM_PSRBITS_FLAGS = 2, // Flags only, no GE - ARM_PSRBITS_ALL = 3, // GE and flags -} armPSRBits; - -// -// This specifies SIMD/VFP type -// -typedef enum armSDFPTypeE { - ARM_SDFPT_NA, // no SIMD/VFP type - ARM_SDFPT_8, // 8 bit value - type not specified - ARM_SDFPT_16, // 16 bit value - type not specified - ARM_SDFPT_32, // 32 bit value - type not specified - ARM_SDFPT_64, // 64 bit value - type not specified - ARM_SDFPT_F16, // floating point 16 bit value - ARM_SDFPT_F32, // floating point 32 bit value - ARM_SDFPT_F64, // floating point 64 bit value - ARM_SDFPT_I8, // integer 8 bit value - ARM_SDFPT_I16, // integer 16 bit value - ARM_SDFPT_I32, // integer 32 bit value - ARM_SDFPT_I64, // integer 64 bit value - ARM_SDFPT_P8, // polynomial 8 bit value - ARM_SDFPT_S8, // signed 8 bit value - ARM_SDFPT_S16, // signed 16 bit value - ARM_SDFPT_S32, // signed 32 bit value - ARM_SDFPT_S64, // signed 64 bit value - ARM_SDFPT_U8, // unsigned 8 bit value - ARM_SDFPT_U16, // unsigned 16 bit value - ARM_SDFPT_U32, // unsigned 32 bit value - ARM_SDFPT_U64, // unsigned 64 bit value -} armSDFPType; - -// -// Type to hold a modified immediate constant value for SIMD and VFP instructions -// -typedef union armSdfpMItypeU { - Uns64 u64; - Flt64 f64; - Flt32 f32; - struct { - Uns32 w0; - Uns32 w1; - } u32; - struct { - Uns16 h0; - Uns16 h1; - Uns16 h2; - Uns16 h3; - } u16; - struct { - Uns8 b0; - Uns8 b1; - Uns8 b2; - Uns8 b3; - Uns8 b4; - Uns8 b5; - Uns8 b6; - Uns8 b7; - } u8; -} armSdfpMItype; - -// -// This specifies instruction support implied by ISAR registers -// -typedef enum armISARSupportE { - ARM_ISAR_NA = 0, // no ISAR restriction - ARM_ISAR_DIV, // SDIV/UDIV support - ARM_ISAR_BKPT, // BKPT support - ARM_ISAR_CBZ, // CBZ/CBNZ support - ARM_ISAR_BFC, // BFC/BFI/SBFX/UBFX support - ARM_ISAR_CLZ, // CLZ support - ARM_ISAR_SWP, // SWP/SWPB support - ARM_ISAR_BXJ, // BXJ support - ARM_ISAR_BX, // BX support - ARM_ISAR_BLX, // BX support - ARM_ISAR_MOVT, // MOVT/MOV(16)/ADD(12) etc support - ARM_ISAR_IT, // IT support - ARM_ISAR_SXTB, // SXTB/SXTH/UXTB/UXTH support - ARM_ISAR_SXTAB, // SXTAB/SXTAH/UXTAB/UXTAH support - ARM_ISAR_SXTB16, // SXTB16/SXTAB16/UXTB16/UXTAB16 support - ARM_ISAR_SRS, // SRS/RFE and A/R profile CPS - ARM_ISAR_LDM_UR, // user mode LDM/STM, exception return LDM - ARM_ISAR_SETEND, // SETEND support - ARM_ISAR_REV, // REV/REV16/REVSH support - ARM_ISAR_RBIT, // RBIT support - ARM_ISAR_MRS_AR, // A/R profile MRS/MSR and exception return support - ARM_ISAR_UMULL, // UMULL/UMLAL support - ARM_ISAR_UMAAL, // UMAAL support - ARM_ISAR_SMULL, // SMULL/SMLAL support - ARM_ISAR_SMLABB, // SMLABB/SMLABT ... SMULWB/SMULWT support - ARM_ISAR_SMLAD, // SMLAD/SMLADX ... SMUSD/SMUSDX support - ARM_ISAR_MLA, // MLA support - ARM_ISAR_MLS, // MLS support - ARM_ISAR_PLD, // PLD support - ARM_ISAR_PLI, // PLI support - ARM_ISAR_LDRD, // LDRD/STRD support - ARM_ISAR_NOP, // NOP support - ARM_ISAR_MOVLL, // Thumb MOV low->low support - ARM_ISAR_TBB, // TBB/TBH support - ARM_ISAR_LDREX, // LDREX/STREX support - ARM_ISAR_CLREX, // CLREX/LDREXB/LDREXH/STREXB/STREXH support - ARM_ISAR_LDREXD, // LDREXD/STREXD support - ARM_ISAR_SVC, // SVC support - ARM_ISAR_SSAT, // SSAT/USAT support - ARM_ISAR_PKHBT, // PKHBT/PKHTB ... USUB8/USAX support - ARM_ISAR_QADD, // QADD/QDADD/QDSUB/QSUB support - ARM_ISAR_MRS_M, // M profile CPS/MRS/MSR support - ARM_ISAR_DMB, // DMB/DSB/ISB support - ARM_ISAR_LDRBT, // LDRBT/LDRT/STRBT/STRT support - ARM_ISAR_LDRHT, // LDRHT/LDRSBT/LDRSHT/STRHT support - ARM_ISAR_VMRS, // load, store, cp moves to SIMD regs supported (VFP2,VFP3,SIMD) - ARM_ISAR_VFPSQRT, // VFP VSQRT support - ARM_ISAR_VFPDIV, // VFP VDIV support - ARM_ISAR_VFPV3, // VFP v3-only support (also check double/single precision support) - ARM_ISAR_VFPV2, // VFP v2 and later support (also check double/single precision support) - ARM_ISAR_VFPFMAC, // VFP fused multilply accumulate support - ARM_ISAR_VFPCVT3, // VFP v3-only conversion support - ARM_ISAR_VFPCVT2, // VFP v2 and later conversion support - ARM_ISAR_VFPHP, // VFP half precision convert support -} armISARSupport; - -// -// This structure is filled with information extracted from the decoded -// instruction -// -typedef struct armInstructionInfoS { - const char *opcode; // opcode name - const char *format; // disassembly format string - armArchitecture support; // variants on which instruction supported - armISARSupport isar; // ISAR instruction support - Uns32 thisPC; // instruction address - Uns32 instruction; // instruction word - armInstructionType type; // instruction type - armCondition cond; // condition under which instruction executes - armSetFlags f; // set flags? - armShiftOp so; // shifter operation to apply to arg 2 - armIncDec incDec; // increment/decrement action - Uns32 c; // constant value - Uns32 t; // target address - Uns32 rList; // register list - Uns8 crotate; // constant rotation from instruction - Uns8 bytes; // instruction size in bytes (1, 2 or 4) - Uns8 r1; // register 1 - Uns8 r2; // register 2 - Uns8 r3; // register 3 - Uns8 r4; // register 4 - Uns8 sz; // load/store size - Int8 w; // bit operation width - Uns8 cpNum; // coprocessor number - Uns8 cpOp1; // coprocessor opcode1 - Uns8 cpOp2; // coprocessor opcode2 - Bool xs; // sign extend? - Bool tl; // translate? - Bool pi; // post-indexed? - Bool wb; // instruction specifies writeback? - Bool u; // instruction U bit set? - Bool ll; // instruction specifies long load? - Bool ea; // load/store is exclusive access? - armUnalignedAction ua; // unaligned action - Bool ma; // mode action (CPS) - armFlagAction fact; // flag action (CPS) - armFlagAffect faff; // flags affected (CPS) - armPSRBits psrbits; // MSR instruction bits value - Uns8 it; // IT block specification - Uns8 index; // index for VFP scalars - Uns8 nregs; // number of registers for vfp register lists - armSDFPType dt1; // VFP first data type - armSDFPType dt2; // VFP second data type - armSdfpMItype sdfpMI; // VFP modified immediate constant value -} armInstructionInfo; - -#endif - diff --git a/simulators/ovp/armmModel/armDisassemble.h b/simulators/ovp/armmModel/armDisassemble.h deleted file mode 100644 index 5a6b439f..00000000 --- a/simulators/ovp/armmModel/armDisassemble.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DISASSEMBLE_H -#define ARM_DISASSEMBLE_H - -// basic number types -#include "hostapi/impTypes.h" - -// model header files -#include "armTypeRefs.h" - -// -// ARM disassembler, decoded instruction interface -// -const char *armDisassembleInfo(armP arm, armInstructionInfoP info); - -#endif - diff --git a/simulators/ovp/armmModel/armDisassembleFormats.h b/simulators/ovp/armmModel/armDisassembleFormats.h deleted file mode 100644 index 504b8539..00000000 --- a/simulators/ovp/armmModel/armDisassembleFormats.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_DISASSEMBLE_FORMATS_H -#define ARM_DISASSEMBLE_FORMATS_H - -// -// These are placeholders in disassembly decoder -// -#define EMIT_R1 '\001' -#define EMIT_R2 '\002' -#define EMIT_R3 '\003' -#define EMIT_R4 '\004' -#define EMIT_CU '\005' -#define EMIT_CS '\006' -#define EMIT_CX '\007' -#define EMIT_T '\010' -#define EMIT_SHIFT '\011' -#define EMIT_SHIFT_C '\012' -#define EMIT_CPNUM '\013' -#define EMIT_COP1 '\014' -#define EMIT_COP2 '\015' -#define EMIT_CR1 '\016' -#define EMIT_CR2 '\017' -#define EMIT_CR3 '\020' -#define EMIT_OPT '\021' -#define EMIT_WB '\022' -#define EMIT_RLIST '\023' -#define EMIT_U '\024' -#define EMIT_SR '\025' -#define EMIT_FLAGS '\026' -#define EMIT_OPT_MODE '\027' -#define EMIT_LIM '\031' -#define EMIT_WIDTH '\032' -#define EMIT_ITC '\033' -#define EMIT_SZSHIFT '\034' -#define EMIT_R1F '\035' -#define EMIT_FPSCR '\036' -#define EMIT_S1 '\302' -#define EMIT_S2 '\303' -#define EMIT_S3 '\304' -#define EMIT_D1 '\305' -#define EMIT_D2 '\306' -#define EMIT_D3 '\307' -#define EMIT_Z1 '\313' -#define EMIT_Z2 '\314' -#define EMIT_SS1 '\316' -#define EMIT_SS3 '\317' -#define EMIT_C0F '\324' -#define EMIT_SDFP_MI '\325' -#define EMIT_SIMD_RL '\326' -#define EMIT_VFP_RL '\327' - -// -// These are placeholders in disassembly format strings -// -#define EMIT_R1_S "\001" -#define EMIT_R2_S "\002" -#define EMIT_R3_S "\003" -#define EMIT_R4_S "\004" -#define EMIT_CU_S "\005" -#define EMIT_CS_S "\006" -#define EMIT_CX_S "\007" -#define EMIT_T_S "\010" -#define EMIT_SHIFT_S "\011" -#define EMIT_SHIFT_C_S "\012" -#define EMIT_CPNUM_S "\013" -#define EMIT_COP1_S "\014" -#define EMIT_COP2_S "\015" -#define EMIT_CR1_S "\016" -#define EMIT_CR2_S "\017" -#define EMIT_CR3_S "\020" -#define EMIT_OPT_S "\021" -#define EMIT_WB_S "\022" -#define EMIT_RLIST_S "\023" -#define EMIT_U_S "\024" -#define EMIT_SR_S "\025" -#define EMIT_FLAGS_S "\026" -#define EMIT_OPT_MODE_S "\027" -#define EMIT_LIM_S "\031" -#define EMIT_WIDTH_S "\032" -#define EMIT_ITC_S "\033" -#define EMIT_SZSHIFT_S "\034" -#define EMIT_R1F_S "\035" -#define EMIT_FPSCR_S "\036" -#define EMIT_S1_S "\302" -#define EMIT_S2_S "\303" -#define EMIT_S3_S "\304" -#define EMIT_D1_S "\305" -#define EMIT_D2_S "\306" -#define EMIT_D3_S "\307" -#define EMIT_Z1_S "\313" -#define EMIT_Z2_S "\314" -#define EMIT_SS1_S "\316" -#define EMIT_SS3_S "\317" -#define EMIT_C0F_S "\324" -#define EMIT_SDFP_MI_S "\325" -#define EMIT_SIMD_RL_S "\326" -#define EMIT_VFP_RL_S "\327" - -// -// These are disassembly format strings -// -#define FMT_NONE "" -#define FMT_R1 EMIT_R1_S -#define FMT_R1_R2 EMIT_R1_S "," EMIT_R2_S -#define FMT_R1_R2_R3 EMIT_R1_S "," EMIT_R2_S "," EMIT_R3_S -#define FMT_R1_R2_R3_R4 EMIT_R1_S "," EMIT_R2_S "," EMIT_R3_S "," EMIT_R4_S -#define FMT_XIMM EMIT_CX_S -#define FMT_SIMM EMIT_CS_S -#define FMT_UIMM EMIT_CU_S -#define FMT_R1_SIMM EMIT_R1_S "," EMIT_CS_S -#define FMT_R1_UIMM EMIT_R1_S "," EMIT_CU_S -#define FMT_R1_R2_SIMM EMIT_R1_S "," EMIT_R2_S "," EMIT_CS_S -#define FMT_R1_R2_UIMM EMIT_R1_S "," EMIT_R2_S "," EMIT_CU_S -#define FMT_R1_R2_SHIFT_SIMM EMIT_R1_S "," EMIT_R2_S "," EMIT_SHIFT_C_S -#define FMT_R1_R2_SHIFT_R3 EMIT_R1_S "," EMIT_R2_S "," EMIT_SHIFT_S " " EMIT_R3_S -#define FMT_R1_R2_SHIFT EMIT_R1_S "," EMIT_R2_S "," EMIT_SHIFT_S -#define FMT_R1_R2_R3_SHIFT_SIMM EMIT_R1_S "," EMIT_R2_S "," EMIT_R3_S "," EMIT_SHIFT_C_S -#define FMT_R1_R2_R3_SHIFT_R4 EMIT_R1_S "," EMIT_R2_S "," EMIT_R3_S "," EMIT_SHIFT_S " " EMIT_R4_S -#define FMT_R1_R2_R3_SHIFT EMIT_R1_S "," EMIT_R2_S "," EMIT_R3_S "," EMIT_SHIFT_S -#define FMT_R1_WIDTH_R2 EMIT_R1_S "," EMIT_WIDTH_S "," EMIT_R2_S -#define FMT_R1_WIDTH_R2_SHIFT_SIMM EMIT_R1_S "," EMIT_WIDTH_S "," EMIT_R2_S "," EMIT_SHIFT_C_S -#define FMT_R1_ADDR_R2_SIMM EMIT_R1_S ",[" EMIT_R2_S "1],*" EMIT_CS_S "2]" EMIT_WB_S -#define FMT_R1_ADDR_R2_R3 EMIT_R1_S ",[" EMIT_R2_S "1]," EMIT_U_S EMIT_R3_S "2]" EMIT_WB_S -#define FMT_R1_ADDR_R2_R3_SHIFT_SIMM EMIT_R1_S ",[" EMIT_R2_S "1]," EMIT_U_S EMIT_R3_S "," EMIT_SHIFT_C_S "2]" EMIT_WB_S -#define FMT_R1_ADDR_R2_R3_SHIFT EMIT_R1_S ",[" EMIT_R2_S "1]," EMIT_U_S EMIT_R3_S "," EMIT_SHIFT_S "2]" EMIT_WB_S -#define FMT_R1_R4_ADDR_R2_SIMM EMIT_R1_S "," EMIT_R4_S ",[" EMIT_R2_S "1],*" EMIT_CS_S "2]" EMIT_WB_S -#define FMT_ADDR_R1_SIMM "[" EMIT_R1_S "1],*" EMIT_CS_S "2]" EMIT_WB_S -#define FMT_ADDR_R1_R2 "[" EMIT_R1_S "1]," EMIT_U_S EMIT_R2_S "2]" EMIT_WB_S -#define FMT_ADDR_R1_R2_SHIFT_SIMM "[" EMIT_R1_S "1]," EMIT_U_S EMIT_R2_S "," EMIT_SHIFT_C_S "2]" EMIT_WB_S -#define FMT_ADDR_R1_R2_SHIFT "[" EMIT_R1_S "1]," EMIT_U_S EMIT_R2_S "," EMIT_SHIFT_S "2]" EMIT_WB_S -#define FMT_R1_R2_ADDR_R3_SIMM EMIT_R1_S "," EMIT_R2_S ",[" EMIT_R3_S "1],*" EMIT_CS_S "2]" -#define FMT_R1_R2_R4_ADDR_R3_SIMM EMIT_R1_S "," EMIT_R2_S "," EMIT_R4_S ",[" EMIT_R3_S "1],*" EMIT_CS_S "2]" -#define FMT_R1_R4_ADDR_R2_SIMM EMIT_R1_S "," EMIT_R4_S ",[" EMIT_R2_S "1],*" EMIT_CS_S "2]" EMIT_WB_S -#define ADDR_R1_R2_SZSHIFT ",[" EMIT_R1_S "," EMIT_R2_S ",*" EMIT_SZSHIFT_S "]" -#define FMT_CPNUM_CR1_SIMM EMIT_CPNUM_S "," EMIT_CR1_S ",[" EMIT_R2_S "1],*" EMIT_CS_S "2]" EMIT_WB_S -#define FMT_CPNUM_CR1_UNINDEXED EMIT_CPNUM_S "," EMIT_CR1_S ",[" EMIT_R2_S "],{" EMIT_OPT_S "}" -#define FMT_SR_R1 EMIT_SR_S "," EMIT_R1_S -#define FMT_R1_SR EMIT_R1_S "," EMIT_SR_S -#define FMT_R1_WB EMIT_R1_S EMIT_WB_S -#define FMT_R1_WB_UIMM EMIT_R1_S EMIT_WB_S "," EMIT_CU_S -#define FMT_T EMIT_T_S -#define FMT_R1_T EMIT_R1_S "," EMIT_T_S -#define FMT_CPNUM_COP1_CR1_CR2_CR3_COP2 EMIT_CPNUM_S "," EMIT_COP1_S "," EMIT_CR1_S "," EMIT_CR2_S "," EMIT_CR3_S ",{" EMIT_COP2_S "}" -#define FMT_CPNUM_COP1_R1_R2_CR3 EMIT_CPNUM_S "," EMIT_COP1_S "," EMIT_R1_S "," EMIT_R2_S "," EMIT_CR3_S -#define FMT_CPNUM_COP1_R1_CR2_CR3_COP2 EMIT_CPNUM_S "," EMIT_COP1_S "," EMIT_R1_S "," EMIT_CR2_S "," EMIT_CR3_S ",{" EMIT_COP2_S "}" -#define FMT_CPNUM_COP1_R1F_CR2_CR3_COP2 EMIT_CPNUM_S "," EMIT_COP1_S "," EMIT_R1F_S "," EMIT_CR2_S "," EMIT_CR3_S ",{" EMIT_COP2_S "}" -#define FMT_RLIST EMIT_RLIST_S -#define FMT_SIMD_RL EMIT_SIMD_RL_S -#define FMT_VFP_RL EMIT_VFP_RL_S -#define FMT_R1_RLIST EMIT_R1_S EMIT_WB_S "," EMIT_RLIST_S -#define FMT_R1_RLIST_T EMIT_R1_S "!," EMIT_RLIST_S -#define FMT_R1_RLIST_UM EMIT_R1_S EMIT_WB_S "," EMIT_RLIST_S "^" -#define FMT_R1_VFP_RL EMIT_R1_S EMIT_WB_S "," EMIT_VFP_RL_S -#define FMT_R1_SIMD_RL EMIT_R1_S EMIT_WB_S "," EMIT_SIMD_RL_S -#define FMT_FLAGS_OPT_MODE EMIT_FLAGS_S ",*" EMIT_OPT_MODE_S -#define FMT_LIM EMIT_LIM_S -#define FMT_R1_R2_LSB_WIDTH EMIT_R1_S "," EMIT_R2_S "," EMIT_CU_S "," EMIT_WIDTH_S -#define FMT_R1_LSB_WIDTH EMIT_R1_S "," EMIT_CU_S "," EMIT_WIDTH_S -#define FMT_ITC EMIT_ITC_S -#define FMT_R1_FPSCR EMIT_R1F_S "," EMIT_FPSCR_S -#define FMT_FPSCR_R1 EMIT_FPSCR_S "," EMIT_R1_S -#define FMT_R1_S2 EMIT_R1_S "," EMIT_S2_S -#define FMT_R1_Z2 EMIT_R1_S "," EMIT_Z2_S -#define FMT_S1_F0 EMIT_S1_S "," EMIT_C0F_S -#define FMT_S1_S2 EMIT_S1_S "," EMIT_S2_S -#define FMT_S1_R2 EMIT_S1_S "," EMIT_R2_S -#define FMT_S1_S2_S3 EMIT_S1_S "," EMIT_S2_S "," EMIT_S3_S -#define FMT_S1_S2_UIMM EMIT_S1_S "," EMIT_S2_S "," EMIT_CU_S -#define FMT_S1_SDFP_MI EMIT_S1_S "," EMIT_SDFP_MI_S -#define FMT_S1_ADDR_R2_SIMM EMIT_S1_S ",[" EMIT_R2_S "1],*" EMIT_CS_S "2]" -#define FMT_S1_SDFP_MI EMIT_S1_S "," EMIT_SDFP_MI_S -#define FMT_Z1_R2 EMIT_Z1_S "," EMIT_R2_S -#define FMT_R1_R2_D3 EMIT_R1_S "," EMIT_R2_S "," EMIT_D3_S -#define FMT_D1_R2_R3 EMIT_D1_S "," EMIT_R2_S "," EMIT_R3_S -#define FMT_D1_ADDR_R2_SIMM EMIT_D1_S ",[" EMIT_R2_S "1],*" EMIT_CS_S "2]" -#define FMT_R1_R2_SS3 EMIT_R1_S "," EMIT_R2_S "," EMIT_SS3_S -#define FMT_SS1_R2_R3 EMIT_SS1_S "," EMIT_R2_S "," EMIT_R3_S - - -#endif diff --git a/simulators/ovp/armmModel/armEmit.h b/simulators/ovp/armmModel/armEmit.h deleted file mode 100644 index 80f10f1d..00000000 --- a/simulators/ovp/armmModel/armEmit.h +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_EMIT_H -#define ARM_EMIT_H - -// VMI header files -#include "vmi/vmiTypes.h" - -// model header files -#include "armMode.h" -#include "armTypeRefs.h" - - -//////////////////////////////////////////////////////////////////////////////// -// INTERWORKING -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code to interwork if required, depending on LSB of target address -// -void armEmitInterworkLSB(armMorphStateP state, vmiReg ra); - - -//////////////////////////////////////////////////////////////////////////////// -// INTEGER OPCODES -//////////////////////////////////////////////////////////////////////////////// - -// -// rd = simPC (true) -// -void armEmitGetTruePC(armMorphStateP state, vmiReg rd); - -// -// r15 = simPC (accoring to ARM pipeline) -// -void armEmitGetPC(armMorphStateP state); - -// -// rd = c -// -void armEmitMoveRC( - armMorphStateP state, - Uns32 bits, - vmiReg rd, - Uns64 c -); - -// -// rd = ra -// -void armEmitMoveRR( - armMorphStateP state, - Uns32 bits, - vmiReg rd, - vmiReg ra -); - -// -// rd = ra -// -void armEmitMoveExtendRR( - armMorphStateP state, - Uns32 destBits, - vmiReg rd, - Uns32 srcBits, - vmiReg ra, - Bool signExtend -); - -// -// rd = (flag==select1) ? c1 : c2 -// -void armEmitCondMoveRCC( - armMorphStateP state, - Uns32 bits, - vmiReg flag, - Bool select1, - vmiReg rd, - Uns64 c1, - Uns64 c2 -); - -// -// rd = ra -// -void armEmitUnopRR( - armMorphStateP state, - Uns32 bits, - vmiUnop op, - vmiReg rd, - vmiReg ra, - vmiFlagsCP flags -); - -// -// rd = c -// -void armEmitUnopRC( - armMorphStateP state, - Uns32 bits, - vmiUnop op, - vmiReg rd, - Uns64 c, - vmiFlagsCP flags -); - -// -// rd = rd ra -// -void armEmitBinopRR( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - vmiReg ra, - vmiFlagsCP flags -); - -// -// rd = rd c -// -void armEmitBinopRC( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - Uns64 c, - vmiFlagsCP flags -); - -// -// rd = ra rb -// -void armEmitBinopRRR( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - vmiReg ra, - vmiReg rb, - vmiFlagsCP flags -); - -// -// rd = ra c -// -void armEmitBinopRRC( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - vmiReg ra, - Uns64 c, - vmiFlagsCP flags -); - -// -// Generate shift mask prefix (sets mask to 255) -// -void armEmitSetShiftMask(void); - -// -// rdh:rdl = ra*rb -// -void armEmitMulopRRR( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rdh, - vmiReg rdl, - vmiReg ra, - vmiReg rb, - vmiFlagsCP flags -); - - -//////////////////////////////////////////////////////////////////////////////// -// FLOATING POINT OPCODES -//////////////////////////////////////////////////////////////////////////////// - -// -// fd = fa fb fc -// -void armEmitFTernopSimdRRRR( - armMorphStateP state, - vmiFType type, - Uns32 num, - vmiFTernop op, - vmiReg fd, - vmiReg fa, - vmiReg fb, - vmiReg fc, - Bool roundInt -); - -// -// fd = fa fb -// -void armEmitFBinopSimdRRR( - armMorphStateP state, - vmiFType type, - Uns32 num, - vmiFBinop op, - vmiReg fd, - vmiReg fa, - vmiReg fb -); - -// -// fd = fa -// -void armEmitFUnopSimdRR( - armMorphStateP state, - vmiFType type, - Uns32 num, - vmiFUnop op, - vmiReg fd, - vmiReg fa -); - -// -// fd = fa -// -void armEmitFConvertRR( - armMorphStateP state, - vmiFType destType, - vmiReg fd, - vmiFType srcType, - vmiReg fa, - vmiFPRC round -); - -// -// compare fa to fb, setting relation and flags -// -void armEmitFCompareRR( - armMorphStateP state, - vmiFType type, - vmiReg relation, - vmiReg fa, - vmiReg fb, - Bool allowQNaN, - Bool setSticky -); - - -//////////////////////////////////////////////////////////////////////////////// -// LOAD AND STORE OPCODES -//////////////////////////////////////////////////////////////////////////////// - -// -// mem[ra+offset] = rb (when ra!=VMI_NOREG) -// mem[offset] = rb (when ra==VMI_NOREG) -// -void armEmitStoreRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg ra, - vmiReg rb -); - -// -// mem[ra+offset] = rbH:rbL (when ra!=VMI_NOREG) -// mem[offset] = rbH:rbL (when ra==VMI_NOREG) -// -void armEmitStoreRRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg ra, - vmiReg rbL, - vmiReg rbH -); - -// -// rd = mem[ra+offset] (when ra!=VMI_NOREG) -// rd = mem[offset] (when ra==VMI_NOREG) -// -void armEmitLoadRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg rd, - vmiReg ra, - Bool signExtend, - Bool isReturn -); - -// -// rdH:rdL = mem[ra+offset] (when ra!=VMI_NOREG) -// rdH:rdL = mem[offset] (when ra==VMI_NOREG) -// -void armEmitLoadRRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg rdL, - vmiReg rdH, - vmiReg ra, - vmiReg rt, - Bool signExtend, - Bool isReturn -); - -// -// trystore mem[ra+offset] (when ra!=VMI_NOREG) -// trystore mem[offset] (when ra==VMI_NOREG) -// -void armEmitTryStoreRC( - armMorphStateP state, - Uns32 bits, - Addr offset, - vmiReg ra -); - - -//////////////////////////////////////////////////////////////////////////////// -// COMPARE OPERATIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// flag = ra rb -// -void armEmitCompareRR( - armMorphStateP state, - Uns32 bits, - vmiCondition cond, - vmiReg ra, - vmiReg rb, - vmiReg flag -); - -// -// flag = ra c -// -void armEmitCompareRC( - armMorphStateP state, - Uns32 bits, - vmiCondition cond, - vmiReg ra, - Uns64 c, - vmiReg flag -); - - -//////////////////////////////////////////////////////////////////////////////// -// INTER-INSTRUCTION CONDITIONAL AND UNCONDITIONAL JUMPS -//////////////////////////////////////////////////////////////////////////////// - -// -// Structure holding information about a jump -// -typedef struct armJumpInfoS { - vmiReg linkReg; // link register - vmiJumpHint hint; // call hint - Uns32 linkPC; // address to put in link register -} armJumpInfo, *armJumpInfoP; - -// -// Perform an unconditional direct jump. -// -void armEmitUncondJump( - armMorphStateP state, - armJumpInfoP ji -); - -// -// Perform an unconditional indirect jump. -// -void armEmitUncondJumpReg( - armMorphStateP state, - armJumpInfoP ji, - vmiReg toReg -); - -// -// Perform a conditional direct jump if the condition flag is non-zero -// (jumpIfTrue) or zero (not jumpIfTrue). -// -void armEmitCondJump( - armMorphStateP state, - armJumpInfoP ji, - vmiReg flag, - Bool jumpIfTrue -); - -// -// Perform an implicit unconditional direct jump if required -// -void armEmitImplicitUncondJump(armMorphStateP state); - - -//////////////////////////////////////////////////////////////////////////////// -// INTRA-INSTRUCTION CONDITIONAL AND UNCONDITIONAL JUMPS -//////////////////////////////////////////////////////////////////////////////// - -// -// Create and return a new label. -// -vmiLabelP armEmitNewLabel(void); - -// -// Insert a label previously created by vmimtNewLabel at the current location. -// -void armEmitInsertLabel(vmiLabelP label); - -// -// Perform an unconditional jump to the passed local label. -// -void armEmitUncondJumpLabel(vmiLabelP toLabel); - -// -// Perform a conditional jump if the condition flag is non-zero (jumpIfTrue) -// or zero (not jumpIfTrue). The target location is the passed local label. -// -void armEmitCondJumpLabel(vmiReg flag, Bool jumpIfTrue, vmiLabelP toLabel); - -// -// Test the register value by performing bitwise AND with the passed constant -// value, and jump to 'toLabel' if condition 'cond' is satisfied. -// -void armEmitTestRCJumpLabel( - Uns32 bits, - vmiCondition cond, - vmiReg r, - Uns64 c, - vmiLabelP toLabel -); - -// -// Compare the register value by performing subtraction of the passed constant -// value, and jump to 'toLabel' if condition 'cond' is satisfied. -// -void armEmitCompareRCJumpLabel( - Uns32 bits, - vmiCondition cond, - vmiReg r, - Uns64 c, - vmiLabelP toLabel -); - - -//////////////////////////////////////////////////////////////////////////////// -//// CALLBACK FUNCTION INTERFACE -//////////////////////////////////////////////////////////////////////////////// - -// -// Add processor argument to the stack frame -// -void armEmitArgProcessor(armMorphStateP state); - -// -// Add Uns32 argument to the stack frame -// -void armEmitArgUns32(armMorphStateP state, Uns32 arg); - -// -// Add register argument to the stack frame -// -void armEmitArgReg(armMorphStateP state, Uns32 bits, vmiReg r); - -// -// Add program counter argument to the stack frame -// -void armEmitArgSimPC(armMorphStateP state, Uns32 bits); - -// -// Make a call with all current stack frame arguments -// -void armEmitCall(armMorphStateP state, vmiCallFn arg); - -// -// As above but generate a function result (placed in rd) -// -void armEmitCallResult( - armMorphStateP state, - vmiCallFn arg, - Uns32 bits, - vmiReg rd -); - - -//////////////////////////////////////////////////////////////////////////////// -// SIMULATOR CONTROL -//////////////////////////////////////////////////////////////////////////////// - -// -// Stop simulation of the current processor -// -void armEmitExit(void); - -// -// Emit code to wait for the passed reason -// -void armEmitWait(armMorphStateP state, armDisable reason); - -// -// Terminate the current block -// -void armEmitEndBlock(void); - -// -// Emit code to validate the current block mode -// -void armEmitValidateBlockMask(armBlockMask blockMask); - -#endif diff --git a/simulators/ovp/armmModel/armExceptionTypes.h b/simulators/ovp/armmModel/armExceptionTypes.h deleted file mode 100644 index 7810f72d..00000000 --- a/simulators/ovp/armmModel/armExceptionTypes.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_EXCEPTION_TYPES_H -#define ARM_EXCEPTION_TYPES_H - -// -// This enumerates exceptions -// -typedef enum armExceptNumE { - AEN_None = 0, - AEN_Reset = 1, - AEN_NMI = 2, - AEN_HardFault = 3, - AEN_MemManage = 4, - AEN_BusFault = 5, - AEN_UsageFault = 6, - AEN_SVCall = 11, - AEN_DebugMonitor = 12, - AEN_PendSV = 14, - AEN_SysTick = 15, - AEN_ExternalInt0 = 16, - AEN_LAST = 512 // KEEP LAST: for sizing -} armExceptNum; - -// -// This identifies whether the passed exception is an interrupt (and whether -// SCR.SLEEPONEXIT applies to this exception type) -// -#define EX_IS_INTERRUPT(_E) ((_E)>=AEN_PendSV) - -// -// This enumerates the context of a load/store exception -// -typedef enum armExceptCxtE { - AEC_None = 0, - AEC_PushStack, - AEC_PopStack, - AEC_ReadVector, - AEC_PreserveFPState -} armExceptCxt; - -// -// This defines permanently-enabled exceptions -// -#define ARM_EXCEPT_PERMANENT_ENABLE ( \ - (1 << AEN_Reset) | \ - (1 << AEN_NMI) | \ - (1 << AEN_HardFault) | \ - (1 << AEN_SVCall) | \ - (1 << AEN_PendSV) | \ - (1 << AEN_SysTick) \ -) - -// -// Utility macros for accessing exception bitmasks -// -#define EX_MASK_INDEX(_N) ((_N)/32) -#define EX_MASK_BIT(_N) ((_N)&31) -#define EX_MASK_MASK(_N) (1<> EX_MASK_BIT(_N)) & 1) -#define EX_MASK_SET_1(_M, _N) _M[EX_MASK_INDEX(_N)] |= EX_MASK_MASK(_N) -#define EX_MASK_SET_0(_M, _N) _M[EX_MASK_INDEX(_N)] &= ~EX_MASK_MASK(_N) - -#define EX_MASK_SET_V(_M, _N, _V) { \ - EX_MASK_SET_0(_M, _N); \ - _M[EX_MASK_INDEX(_N)] |= ((_V)<> ARM_FP32_EXP_SHIFT) -#define ARM_FP32_FRACTION(_F) ((_F) & ((1<> ARM_FP16_EXP_SHIFT) -#define ARM_FP16_FRACTION(_F) ((_F) & ((1< -// -#define MORPH_SET_SMLA_XY(_NAME) \ - [ARM_IT_##_NAME##BB] = {morphCB:armEmit##_NAME##BB}, \ - [ARM_IT_##_NAME##BT] = {morphCB:armEmit##_NAME##BT}, \ - [ARM_IT_##_NAME##TB] = {morphCB:armEmit##_NAME##TB}, \ - [ARM_IT_##_NAME##TT] = {morphCB:armEmit##_NAME##TT} - -// -// Morpher attributes for ARM instructions like SMLAW -// -#define MORPH_SET_SMLAW_Y(_NAME) \ - [ARM_IT_##_NAME##B] = {morphCB:armEmit##_NAME##B}, \ - [ARM_IT_##_NAME##T] = {morphCB:armEmit##_NAME##T} - -// -// Morpher attributes for parallel add/subtract instructions -// -#define MORPH_SET_PAS(_NAME, _OP1, _OP2, _SEXTEND, _SETGE, _HALVE) \ - [ARM_IT_##_NAME##ADD16] = {morphCB:armEmitParallelBinop16, binop:_OP1, binop2:_OP1, exchange:0, sextend:_SEXTEND, setGE:_SETGE, halve:_HALVE}, \ - [ARM_IT_##_NAME##ASX] = {morphCB:armEmitParallelBinop16, binop:_OP2, binop2:_OP1, exchange:1, sextend:_SEXTEND, setGE:_SETGE, halve:_HALVE}, \ - [ARM_IT_##_NAME##SAX] = {morphCB:armEmitParallelBinop16, binop:_OP1, binop2:_OP2, exchange:1, sextend:_SEXTEND, setGE:_SETGE, halve:_HALVE}, \ - [ARM_IT_##_NAME##SUB16] = {morphCB:armEmitParallelBinop16, binop:_OP2, binop2:_OP2, exchange:0, sextend:_SEXTEND, setGE:_SETGE, halve:_HALVE}, \ - [ARM_IT_##_NAME##ADD8] = {morphCB:armEmitParallelBinop8, binop:_OP1, exchange:0, sextend:_SEXTEND, setGE:_SETGE, halve:_HALVE}, \ - [ARM_IT_##_NAME##SUB8] = {morphCB:armEmitParallelBinop8, binop:_OP2, exchange:0, sextend:_SEXTEND, setGE:_SETGE, halve:_HALVE} - -// -// Morpher attributes for signed multiply instructions with optional argument exchange -// -#define MORPH_SET_MEDIA_X(_NAME, _OP1, _OP2) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_OP1, binop:_OP2, exchange:0}, \ - [ARM_IT_##_NAME##X] = {morphCB:armEmit##_OP1, binop:_OP2, exchange:1} - -// -// Morpher attributes for signed multiply instructions with optional rounding -// -#define MORPH_SET_MEDIA_R(_NAME, _OP1, _OP2, _ACC) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_OP1, binop:_OP2, round:0, accumulate:_ACC}, \ - [ARM_IT_##_NAME##R] = {morphCB:armEmit##_OP1, binop:_OP2, round:1, accumulate:_ACC} - -// -// Morpher attributes for ARM instructions like PLD -// -#define MORPH_SET_PLD(_NAME) \ - [ARM_IT_##_NAME##_IMM] = {morphCB:armEmitNOP}, \ - [ARM_IT_##_NAME##_RM] = {morphCB:armEmitNOP}, \ - [ARM_IT_##_NAME##_RM_SHFT_IMM] = {morphCB:armEmitNOP} - - -//////////////////////////////////////////////////////////////////////////////// -// THUMB INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Morpher attributes for Thumb instructions like ADD (4) -// -#define MORPH_SET_ADD4(_NAME, _OP, _FLAGS_RW, _FLAGS_R, _COUT) \ - [ARM_IT_##_NAME] = {morphCB:armEmitBinopRT, binop:_OP, flagsRW:_FLAGS_RW, flagsR:_FLAGS_R, shiftCOut:_COUT} - -// -// Morpher attributes for Thumb instructions like ADD (6) -// -#define MORPH_SET_ADD6(_NAME, _OP, _FLAGS_RW, _FLAGS_R, _COUT) \ - [ARM_IT_##_NAME] = {morphCB:armEmitBinopI, binop:_OP, flagsRW:_FLAGS_RW, flagsR:_FLAGS_R, shiftCOut:_COUT} - -// -// Morpher attributes for Thumb instructions like ADD (7) -// -#define MORPH_SET_ADD7(_NAME, _OP, _FLAGS_RW, _FLAGS_R, _COUT) \ - [ARM_IT_##_NAME] = {morphCB:armEmitBinopIT, binop:_OP, flagsRW:_FLAGS_RW, flagsR:_FLAGS_R, shiftCOut:_COUT} - -// -// Morpher attributes for Thumb instructions like MOV (3) -// -#define MORPH_SET_MOV3(_NAME, _OP, _FLAGS_RW, _FLAGS_R, _COUT) \ - [ARM_IT_##_NAME] = {morphCB:armEmitUnopR, unop:_OP, flagsRW:_FLAGS_RW, flagsR:_FLAGS_R, shiftCOut:_COUT} - -// -// Morpher attributes for Thumb instructions like ADR -// -#define MORPH_SET_ADR(_NAME, _NEGATE) \ - [ARM_IT_##_NAME] = {morphCB:armEmitBinopADR, binop:vmi_ADD, negate:_NEGATE} - -// -// Morpher attributes for Thumb instructions like CBZ -// -#define MORPH_SET_CBZ(_NAME, _JUMP_IF_TRUE) \ - [ARM_IT_##_NAME] = {morphCB:armEmitCBZ, jumpIfTrue:_JUMP_IF_TRUE} - -// -// Morpher attributes for Thumb instructions like SDIV -// -#define MORPH_SET_SDIV(_NAME, _OP) \ - [ARM_IT_##_NAME] = {morphCB:armEmitDIV, binop:_OP} - -// -// Morpher attributes for Single entry VFP instructions -// -#define MORPH_SET_SINGLE_VFP(_NAME) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_NAME, iType:ARM_TY_VFP} - -// -// Morpher attributes for VFP instructions with D and S versions -// -#define MORPH_SET_VFP_DS(_NAME, _FUNC) \ - [ARM_IT_##_NAME##_S] = {morphCB:armEmit##_FUNC, iType:ARM_TY_VFP, ebytes:4}, \ - [ARM_IT_##_NAME##_D] = {morphCB:armEmit##_FUNC, iType:ARM_TY_VFP, ebytes:8} - -// -// Morpher attributes for VFP instructions with S version only -// -#define MORPH_SET_VFP_S(_NAME, _FUNC) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_FUNC, iType:ARM_TY_VFP, ebytes:4} - -// -// Morpher attributes for VFP instructions doing single precision binary floating point op -// -#define MORPH_SET_VFP_RRR_F(_NAME, _FUNC, _OP, _NEGATE) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_FUNC, iType:ARM_TY_VFP, fbinop:_OP, ebytes:4, negate:_NEGATE} - -// -// Morpher attributes for VFP instructions doing single precision unary floating point op -// -#define MORPH_SET_VFP_RR_F(_NAME, _OP) \ - [ARM_IT_##_NAME] = {morphCB:armEmitVFPUnop, iType:ARM_TY_VFP, funop:_OP, ebytes:4} - -// -// Morpher attributes for VFP VCMP instructions -// -#define MORPH_SET_VFP_VCMP(_NAME, _FUNC, _QNAN) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_FUNC, iType:ARM_TY_VFP, ebytes:4, allowQNaN:_QNAN} - -// -// Morpher attributes for VFP VCVT instructions -// -#define MORPH_SET_VFP_VCVT(_NAME, _FUNC, _BYTES, _SIGN, _RND) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_FUNC, iType:ARM_TY_VFP, ebytes:_BYTES, sextend:_SIGN, roundFPSCR:_RND} - -// -// Morpher attributes for VFP VCVT half precision instructions which may specify top or bottom half -// -#define MORPH_SET_VFP_VCVT_H(_NAME, _FUNC, _BYTES, _TOP) \ - [ARM_IT_##_NAME] = {morphCB:armEmit##_FUNC, iType:ARM_TY_VFP, ebytes:_BYTES, highhalf:_TOP} - -// -// Morpher attributes for single precision VFP Fused Multiply instructions -// -#define MORPH_SET_VFP_FMAC_F(_NAME, _SUB, _NEGATE) \ - [ARM_IT_##_NAME] = {morphCB:armEmitVFusedMAC, iType:ARM_TY_VFP, subtract:_SUB, negate:_NEGATE} - -#endif diff --git a/simulators/ovp/armmModel/armMorphFunctions.h b/simulators/ovp/armmModel/armMorphFunctions.h deleted file mode 100644 index 0223d076..00000000 --- a/simulators/ovp/armmModel/armMorphFunctions.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_MORPH_FUNCTIONS_H -#define ARM_MORPH_FUNCTIONS_H - -// model header files -#include "armMode.h" -#include "armMorph.h" - -// unop instructions -ARM_MORPH_FN(armEmitUnopI); -ARM_MORPH_FN(armEmitUnopR); -ARM_MORPH_FN(armEmitUnopRSI); -ARM_MORPH_FN(armEmitUnopRSR); -ARM_MORPH_FN(armEmitUnopRSRT); -ARM_MORPH_FN(armEmitUnopRX); - -// binop instructions -ARM_MORPH_FN(armEmitBinopI); -ARM_MORPH_FN(armEmitBinopR); -ARM_MORPH_FN(armEmitBinopRT); -ARM_MORPH_FN(armEmitBinopIT); -ARM_MORPH_FN(armEmitBinopADR); -ARM_MORPH_FN(armEmitBinopRSI); -ARM_MORPH_FN(armEmitBinopRSR); -ARM_MORPH_FN(armEmitBinopRX); - -// cmpop instructions -ARM_MORPH_FN(armEmitCmpopI); -ARM_MORPH_FN(armEmitCmpopR); -ARM_MORPH_FN(armEmitCmpopRSI); -ARM_MORPH_FN(armEmitCmpopRX); - -// multiply and divide instructions -ARM_MORPH_FN(armEmitMUL); -ARM_MORPH_FN(armEmitMLA); -ARM_MORPH_FN(armEmitMLS); -ARM_MORPH_FN(armEmitDIV); -ARM_MORPH_FN(armEmitMULL); -ARM_MORPH_FN(armEmitMLAL); - -// branch instructions -ARM_MORPH_FN(armEmitBranchC); -ARM_MORPH_FN(armEmitBranchR); -ARM_MORPH_FN(armEmitBLX); - -// miscellaneous instructions -ARM_MORPH_FN(armEmitCLZ); -ARM_MORPH_FN(armEmitBKPT); -ARM_MORPH_FN(armEmitSWI); - -// load and store instructions -ARM_MORPH_FN(armEmitLDRI); -ARM_MORPH_FN(armEmitLDRR); -ARM_MORPH_FN(armEmitLDRRSI); -ARM_MORPH_FN(armEmitLDM1); -ARM_MORPH_FN(armEmitSTRI); -ARM_MORPH_FN(armEmitSTRR); -ARM_MORPH_FN(armEmitSTRRSI); -ARM_MORPH_FN(armEmitSTM1); - -// coprocessor instructions -ARM_MORPH_FN(armEmitUsageFaultCP); - -// status register access instructions -ARM_MORPH_FN(armEmitMRS); -ARM_MORPH_FN(armEmitMSR); - -// DSP data processing instructions -ARM_MORPH_FN(armEmitQADD); -ARM_MORPH_FN(armEmitQSUB); -ARM_MORPH_FN(armEmitQDADD); -ARM_MORPH_FN(armEmitQDSUB); - -// DSP multiply instructions -ARM_MORPH_FN(armEmitSMLABB); -ARM_MORPH_FN(armEmitSMLABT); -ARM_MORPH_FN(armEmitSMLATB); -ARM_MORPH_FN(armEmitSMLATT); -ARM_MORPH_FN(armEmitSMLALBB); -ARM_MORPH_FN(armEmitSMLALBT); -ARM_MORPH_FN(armEmitSMLALTB); -ARM_MORPH_FN(armEmitSMLALTT); -ARM_MORPH_FN(armEmitSMLAWB); -ARM_MORPH_FN(armEmitSMLAWT); -ARM_MORPH_FN(armEmitSMULBB); -ARM_MORPH_FN(armEmitSMULBT); -ARM_MORPH_FN(armEmitSMULTB); -ARM_MORPH_FN(armEmitSMULTT); -ARM_MORPH_FN(armEmitSMULWB); -ARM_MORPH_FN(armEmitSMULWT); - -// hint instructions -ARM_MORPH_FN(armEmitNOP); -ARM_MORPH_FN(armEmitWFE); -ARM_MORPH_FN(armEmitWFI); -ARM_MORPH_FN(armEmitSEV); - -// move instructions -ARM_MORPH_FN(armEmitMOVW); -ARM_MORPH_FN(armEmitMOVT); - -// multiply instructions -ARM_MORPH_FN(armEmitMAAL); - -// synchronization instructions -ARM_MORPH_FN(armEmitLDREX); -ARM_MORPH_FN(armEmitSTREX); -ARM_MORPH_FN(armEmitCLREX); - -// miscellaneous instructions -ARM_MORPH_FN(armEmitCPS); - -// branch instructions -ARM_MORPH_FN(armEmitCBZ); -ARM_MORPH_FN(armEmitTB); - -// basic media instructions -ARM_MORPH_FN(armEmitUSAD8); -ARM_MORPH_FN(armEmitUSADA8); -ARM_MORPH_FN(armEmitSBFX); -ARM_MORPH_FN(armEmitBFC); -ARM_MORPH_FN(armEmitBFI); -ARM_MORPH_FN(armEmitUBFX); - -// parallel add/subtract instructions -ARM_MORPH_FN(armEmitParallelBinop8); -ARM_MORPH_FN(armEmitParallelBinop16); - -// packing, unpacking, saturation and reversal instructions -ARM_MORPH_FN(armEmitPKHBT); -ARM_MORPH_FN(armEmitPKHTB); -ARM_MORPH_FN(armEmitSSAT); -ARM_MORPH_FN(armEmitSSAT16); -ARM_MORPH_FN(armEmitUSAT); -ARM_MORPH_FN(armEmitUSAT16); -ARM_MORPH_FN(armEmitSXTAB); -ARM_MORPH_FN(armEmitUXTAB); -ARM_MORPH_FN(armEmitSXTAB16); -ARM_MORPH_FN(armEmitUXTAB16); -ARM_MORPH_FN(armEmitSXTAH); -ARM_MORPH_FN(armEmitUXTAH); -ARM_MORPH_FN(armEmitSXTB); -ARM_MORPH_FN(armEmitUXTB); -ARM_MORPH_FN(armEmitSXTB16); -ARM_MORPH_FN(armEmitUXTB16); -ARM_MORPH_FN(armEmitSXTH); -ARM_MORPH_FN(armEmitUXTH); -ARM_MORPH_FN(armEmitSEL); -ARM_MORPH_FN(armEmitREV); -ARM_MORPH_FN(armEmitREV16); -ARM_MORPH_FN(armEmitRBIT); -ARM_MORPH_FN(armEmitREVSH); - -// signed multiply instructions -ARM_MORPH_FN(armEmitSMLXD); -ARM_MORPH_FN(armEmitSMUXD); -ARM_MORPH_FN(armEmitSMLXLD); -ARM_MORPH_FN(armEmitSMMLX); - -// VFP data processing instructions -ARM_MORPH_FN(armEmitVFPUnop); -ARM_MORPH_FN(armEmitVFPBinop); -ARM_MORPH_FN(armEmitVMulAcc_VFP); -ARM_MORPH_FN(armEmitVFusedMAC); -ARM_MORPH_FN(armEmitVMOVI_VFP); -ARM_MORPH_FN(armEmitVMOVR_VFP); -ARM_MORPH_FN(armEmitVABS_VFP); -ARM_MORPH_FN(armEmitVNEG_VFP); -ARM_MORPH_FN(armEmitVCMP_VFP); -ARM_MORPH_FN(armEmitVCMP0_VFP); -ARM_MORPH_FN(armEmitVCVT_SD_VFP); -ARM_MORPH_FN(armEmitVCVT_SH_VFP); -ARM_MORPH_FN(armEmitVCVT_HS_VFP); -ARM_MORPH_FN(armEmitVCVT_XF_VFP); -ARM_MORPH_FN(armEmitVCVT_FX_VFP); -ARM_MORPH_FN(armEmitVCVT_IF_VFP); -ARM_MORPH_FN(armEmitVCVT_FI_VFP); - -// VFP Extension register load/store instructions -ARM_MORPH_FN(armEmitVLDR); -ARM_MORPH_FN(armEmitVSTR); -ARM_MORPH_FN(armEmitVLDM); -ARM_MORPH_FN(armEmitVSTM); - -// VFP 8, 16 and 32-bit transfer instructions -ARM_MORPH_FN(armEmitVMRS); -ARM_MORPH_FN(armEmitVMSR); -ARM_MORPH_FN(armEmitVMOVRS); -ARM_MORPH_FN(armEmitVMOVSR); -ARM_MORPH_FN(armEmitVMOVRZ); -ARM_MORPH_FN(armEmitVMOVZR); -ARM_MORPH_FN(armEmitVDUPR); - -// VFP 64-bit transfer instructions -ARM_MORPH_FN(armEmitVMOVRRD); -ARM_MORPH_FN(armEmitVMOVDRR); -ARM_MORPH_FN(armEmitVMOVRRSS); -ARM_MORPH_FN(armEmitVMOVSSRR); - -// -// If the register index specifies a banked register, return a vmiReg structure -// for the banked register; otherwise, return VMI_NOREG. Also, validate the -// current block mode for banked registers. -// -vmiReg armGetBankedRegMode(Bool useSPProcess, Uns32 r); - -#endif diff --git a/simulators/ovp/armmModel/armRegisters.h b/simulators/ovp/armmModel/armRegisters.h deleted file mode 100644 index d81c54d2..00000000 --- a/simulators/ovp/armmModel/armRegisters.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_REGISTERS_H -#define ARM_REGISTERS_H - -// VMI header files -#include "vmi/vmiTypes.h" - -// model header files -#include "armTypeRefs.h" - - -//////////////////////////////////////////////////////////////////////////////// -// REGISTER ACCESS MACROS -//////////////////////////////////////////////////////////////////////////////// - -// aliases for specific GPRs -#define ARM_REG_SP 13 -#define ARM_REG_LR 14 -#define ARM_REG_PC 15 - -// morph-time macros to calculate offsets to registers in an arm structure -#define ARM_CPU_OFFSET(_F) VMI_CPU_OFFSET(armP, _F) -#define ARM_CPU_REG(_F) VMI_CPU_REG(armP, _F) -#define ARM_CPU_REG_CONST(_F) VMI_CPU_REG_CONST(armP, _F) -#define ARM_CPU_TEMP(_F) VMI_CPU_TEMP(armP, _F) - -// morph-time macros to calculate constant offsets to flags in an arm structure -#define ARM_ZF_CONST ARM_CPU_REG_CONST(aflags.ZF) -#define ARM_NF_CONST ARM_CPU_REG_CONST(aflags.NF) -#define ARM_CF_CONST ARM_CPU_REG_CONST(aflags.CF) -#define ARM_VF_CONST ARM_CPU_REG_CONST(aflags.VF) -#define ARM_HI_CONST ARM_CPU_REG_CONST(oflags.HI) -#define ARM_LT_CONST ARM_CPU_REG_CONST(oflags.LT) -#define ARM_LE_CONST ARM_CPU_REG_CONST(oflags.LE) - -// morph-time macros to calculate variable offsets to flags in an arm structure -#define ARM_AFLAGS ARM_CPU_REG(aflags) -#define ARM_ZF ARM_CPU_REG(aflags.ZF) -#define ARM_NF ARM_CPU_REG(aflags.NF) -#define ARM_CF ARM_CPU_REG(aflags.CF) -#define ARM_VF ARM_CPU_REG(aflags.VF) -#define ARM_QF ARM_CPU_REG(oflags.QF) - -// morph-time macros to calculate offsets to fields in an arm structure -#define ARM_REG(_R) ARM_CPU_REG(regs[_R]) -#define ARM_TREG(_R) ARM_CPU_TEMP(regs[_R]) -#define ARM_TEMP(_R) ARM_CPU_TEMP(temps[_R]) -#define ARM_SP ARM_REG(ARM_REG_SP) -#define ARM_LR ARM_REG(ARM_REG_LR) -#define ARM_PC ARM_TREG(ARM_REG_PC) - -// morph-time macros to calculate offsets to control registers -#define ARM_PSR ARM_CPU_REG(sregs.PSR) -#define ARM_CONTROL ARM_CPU_REG(sregs.CONTROL) -#define ARM_PRIMASK ARM_CPU_REG(sregs.PRIMASK) -#define ARM_FAULTMASK ARM_CPU_REG(sregs.FAULTMASK) -#define ARM_BASEPRI ARM_CPU_REG(sregs.BASEPRI) -#define ARM_FPSCR ARM_CPU_REG(sregs.FPSCR) - -// morph-time macros to calculate offsets to banked registers in an arm structure -#define ARM_BANK_REG(_N, _SET) ARM_CPU_REG(bank.R##_N##_##_SET) -#define ARM_BANK_SP ARM_BANK_REG(13, process) - -// morph-time macro to calculate offset to EA tag in an arm structure -#define ARM_EA_TAG ARM_CPU_REG(exclusiveTag) - -// morph-time macro to calculate offset to ITSTATE in an arm structure -#define ARM_IT_STATE ARM_CPU_REG(itStateRT) - -// morph-time macro to calculate offset to divide target index in an arm structure -#define ARM_DIVIDE_TARGET ARM_CPU_REG(divideTarget) - -// morph-time macro to calculate offset to disable reason, event register and -// pending interrupt state in an arm structure -#define ARM_DISABLE_REASON ARM_CPU_REG(disableReason) -#define ARM_EVENT ARM_CPU_REG(eventRegister) -#define ARM_PENDING ARM_CPU_REG(pendingInterrupt) - -// morph-time macros to calculate offsets to floating point registers in an arm -// structure -#define ARM_FP_FLAGS ARM_CPU_REG(sdfpFlags) -#define ARM_FP_STICKY ARM_CPU_REG(sdfpSticky) -#define ARM_BREG(_R) ARM_CPU_REG(vregs.b[_R]) -#define ARM_HREG(_R) ARM_CPU_REG(vregs.h[_R]) -#define ARM_WREG(_R) ARM_CPU_REG(vregs.w[_R]) -#define ARM_DREG(_R) ARM_CPU_REG(vregs.d[_R]) - -#endif - diff --git a/simulators/ovp/armmModel/armStructure.h b/simulators/ovp/armmModel/armStructure.h deleted file mode 100644 index d464283b..00000000 --- a/simulators/ovp/armmModel/armStructure.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_STRUCTURE_H -#define ARM_STRUCTURE_H - -// VMI header files -#include "vmi/vmiPorts.h" -#include "vmi/vmiTypes.h" - -// model header files -#include "armConfig.h" -#include "armExceptionTypes.h" -#include "armSysRegisters.h" -#include "armMode.h" -#include "armTypeRefs.h" -#include "armVariant.h" - -// processor debug flags -#define ARM_DISASSEMBLE_MASK 0x00000001 -#define ARM_THUMB_MASK 0x00000002 -#define ARM_DEBUG_MMU_MASK 0x00000004 -#define ARM_DEBUG_EXCEPT_MASK 0x00000008 -#define ARM_DUMP_SDFP_REG_MASK 0x00000010 - -#define ARM_DISASSEMBLE(_P) ((_P)->flags & ARM_DISASSEMBLE_MASK) -#define ARM_THUMB(_P) ((_P)->flags & ARM_THUMB_MASK) -#define ARM_DEBUG_MMU(_P) ((_P)->flags & ARM_DEBUG_MMU_MASK) -#define ARM_DEBUG_EXCEPT(_P) ((_P)->flags & ARM_DEBUG_EXCEPT_MASK) -#define ARM_DUMP_SDFP_REG(_P) ((_P)->flags & ARM_DUMP_SDFP_REG_MASK) - -#define ARM_GPR_BITS 32 -#define ARM_GPR_BYTES (ARM_GPR_BITS/8) -#define ARM_GPR_NUM 16 -#define ARM_TEMP_NUM 12 - -#define ARM_VFP_REG_BITS 64 -#define ARM_VFP_REG_BYTES 8 -#define ARM_VFP16_REG_NUM 16 -#define ARM_VFP32_REG_NUM 32 - -#define ARM_EXCEPT_NUM 512 -#define ARM_EXCEPT_MASK_NUM ((ARM_EXCEPT_NUM+31)/32) -#define ARM_INTERRUPT_NUM 496 - -#define ARM_NO_TAG -1 - -// simulator compatibility modes -typedef enum armCompatModeE { - COMPAT_ISA, // conform to the documented ISA - COMPAT_GDB, // conform to gdb simulator - COMPAT_CODE_SOURCERY // conform to ARM CodeSourcery toolchain output (ignore BKPT) -} armCompatMode; - -// arithmetic flags -typedef struct armArithFlagsS { - Uns8 ZF; // zero flag - Uns8 NF; // sign flag - Uns8 CF; // carry flag - Uns8 VF; // overflow flag -} armArithFlags; - -// other flags -typedef struct armOtherFlagsS { - Uns8 HI; // hi flag (created on demand) - Uns8 LT; // lt flag (created on demand) - Uns8 LE; // le flag (created on demand) - Uns8 QF; // saturation flag -} armOtherFlags; - -// ARM PSR (combines APSR, IPSR and EPSR) -typedef union armPSRU { - struct { - Uns32 exceptNum : 9; // exception number - Uns32 align4 : 1; // 4 byte alignment (in stack) - Uns32 IT72 : 6; // if-then state, bits 7:2 - Uns32 GE : 4; // GE bits (unused when no DSP) - Uns32 _u1 : 4; // unused bits - Uns32 T : 1; // Thumb mode bit - Uns32 IT10 : 2; // if-then state, bits 1:0 - Uns32 Q : 1; // DSP overflow/saturate flag - Uns32 V : 1; // overflow flag - Uns32 C : 1; // carry flag - Uns32 Z : 1; // zero flag - Uns32 N : 1; // sign flag - } fields; - Uns32 reg; -} armPSR; - -// PSR Access Macros -#define PSR_FIELD(_A, _F) ((_A)->sregs.PSR.fields._F) -#define IN_USER_MODE(_A) (!PSR_FIELD(_A, exceptNum) && CONTROL_FIELD(_A, threadUnpriv)) -#define IN_THUMB_MODE(_A) PSR_FIELD(_A, T) -#define IN_HANDLER_MODE(_A) (PSR_FIELD(_A, exceptNum) && True) -#define IN_BASE_MODE(_A) IN_USER_MODE(_A) -#define IN_PRIV_MPU_MODE(_A) (!IN_USER_MODE(_A) && MPU_ENABLED(_A)) - -// Masks for fields in PSR -#define PSR_FLAGS 0xf8000000 -#define PSR_NZCV 0xf0000000 -#define PSR_EXCEPT_NUM 0x000001ff -#define PSR_THUMB 0x01000000 -#define PSR_IT10 0x06000000 -#define PSR_IT72 0x0000fc00 -#define PSR_GE 0x000f0000 -#define PSR_GE3 0x00080000 -#define PSR_GE2 0x00040000 -#define PSR_GE1 0x00020000 -#define PSR_GE0 0x00010000 -#define PSR_GE32 (PSR_GE3|PSR_GE2) -#define PSR_GE10 (PSR_GE1|PSR_GE0) -#define PSR_GE30 (PSR_GE32|PSR_GE10) -#define PSR_IT (PSR_IT72 | PSR_IT10) -#define PSR_ALL (PSR_FLAGS | PSR_IT | PSR_THUMB | PSR_GE | PSR_EXCEPT_NUM) -#define PSR_NOT_FLAGS (PSR_ALL & ~(PSR_FLAGS | PSR_GE)) - -// ARM CONTROL -typedef union armCONTROLU { - struct { - Uns32 threadUnpriv : 1; // is thread mode unprivileged? - Uns32 useSP_Process : 1; // use SP_process stack - Uns32 FPCA : 1; // Is FP active in current context? - } fields; - Uns32 reg; -} armCONTROL; - -// CONTROL Access Macros -#define CONTROL_FIELD(_A, _F) ((_A)->sregs.CONTROL.fields._F) -#define USE_SP_PROCESS(_A) CONTROL_FIELD(_A, useSP_Process) - -// Masks for fields in CONTROL -#define CONTROL_FPCA 0x00000004 - -// ARM FPSCR -typedef union armFPSCRU { - struct { - Uns32 IOC : 1; - Uns32 DZC : 1; - Uns32 OFC : 1; - Uns32 UFC : 1; - Uns32 IXC : 1; - Uns32 _u1 : 2; - Uns32 IDC : 1; - Uns32 _u2 : 14; - Uns32 RMode : 2; - Uns32 FZ : 1; - Uns32 DN : 1; - Uns32 AHP : 1; - Uns32 _u3 : 1; - Uns32 V : 1; - Uns32 C : 1; - Uns32 Z : 1; - Uns32 N : 1; - } fields; - Uns32 reg; -} armFPSCR; - -// FPSCR Access Macros -#define FPSCR_MASK 0xf7c0009f -#define FPSCR_REG(_A) ((_A)->sregs.FPSCR.reg) -#define FPSCR_FIELD(_A, _F) ((_A)->sregs.FPSCR.fields._F) - -// Write Masks for fields in other control registers (with no structs) -#define PRIMASK_MASK 0x00000001 -#define FAULTMASK_MASK 0x00000001 -#define BASEPRI_MASK 0x000000ff - -// Special register definitions -typedef struct armSpecialRegsS { - armPSR PSR; - armCONTROL CONTROL; - Uns32 PRIMASK; - Uns32 FAULTMASK; - Uns32 BASEPRI; - armFPSCR FPSCR; -} armSpecialRegs; - -// Banked registers -typedef struct armBankRegsS { - - // process stack pointer - Uns32 R13_process; - -} armBankRegs; - -typedef struct armDomainSetS { - memDomainP external; // external memory domain - memDomainP vmPriv; // virtual code domain, privileged mode - memDomainP vmUser; // virtual code domain, user mode - memDomainP system; // system domain -} armDomainSet, *armDomainSetP; - -typedef enum armPIDSetE { - APS_PHYS, // physical domains (privileged or user mode) - APS_VM_P, // MMU/MPU-managed privileged mode domains - APS_VM_U, // MMU/MPU-managed user mode domains - APS_LAST // KEEP LAST: for sizing -} armPIDSet; - -// decoder callback function to decode instruction at the passed address -#define ARM_DECODER_FN(_NAME) void _NAME( \ - armP arm, \ - Uns32 thisPC, \ - armInstructionInfoP info \ -) -typedef ARM_DECODER_FN((*armDecoderFn)); - -// Callback function to return size of instruction at the passed for the specified mode -#define ARM_ISIZE_FN(_NAME) Uns32 _NAME( \ - armP arm, \ - Uns32 thisPC, \ - Bool isThumb \ -) -typedef ARM_ISIZE_FN((*armIsizeFn)); - -// opaque type for MPU protection region -typedef struct protRegionS *protRegionP; - -// VFP register bank -typedef union armVFPRS { - Uns8 b[ARM_VFP16_REG_NUM*8]; // when viewed as bytes - Uns16 h[ARM_VFP16_REG_NUM*4]; // When viewed as 16 bit halfwords - Uns32 w[ARM_VFP16_REG_NUM*2]; // when viewed as 32-bit words - Uns64 d[ARM_VFP16_REG_NUM]; // when viewed as 64-bit double words -} armVFPR; - -#define FP_REG(_A, _I) ((_A)->vregs.w[(_I)]) - -// floating point control word type -typedef union armFPCWU { - Uns32 u32; // when viewed as composed value - vmiFPControlWord cw; // when viewed as fields -} armFPCW; - -// processor structure -typedef struct armS { - - // TRUE PROCESSOR REGISTERS - armArithFlags aflags; // arithmetic flags - armOtherFlags oflags; // other flags - Uns32 regs[ARM_GPR_NUM]; // current mode GPRs - armSpecialRegs sregs; // special purpose registers - - // SIMULATOR SUPPORT - Uns32 temps[ARM_TEMP_NUM]; // temporary registers - Uns8 itStateRT; // if-then state (run time) - Uns8 itStateMT; // if-then state (morph time) - Uns8 divideTarget; // target of divide instruction - Uns8 disableReason; // reason why processor disabled - Bool eventRegister; // event register - Bool pendingInterrupt; // is interrupt pending? - armMode mode :8; // current processor mode - Bool validHI :1; // is hi flag valid? - Bool validLT :1; // is lt flag valid? - Bool validLE :1; // is le flag valid? - Bool checkEndian :1; // check endian using blockMask? - Bool checkL4 :1; // check interwork using blockMask? - Bool checkUnaligned :1; // check alignment mode using blockMask? - Bool disableTimerRVR0 :1; // disable timer (SYST_RVR==0)? - Bool sleepOnExit :1; // sleeping at exception exit? - Bool denormalInput :1; // input denormal sticky flag - memEndian instructionEndian:1; // instruction endianness - armExceptCxt exceptionContext :3; // exception context - Uns32 exclusiveTag; // tag for active exclusive access - Uns32 exclusiveTagMask; // mask to select exclusive tag bits - Uns32 priorityMask; // priority mask - Uns32 exceptNum; // total number of exceptions - Uns32 exceptMaskNum; // number of words in exception masks - Uns32 timerModulus; // modulus value for counter - Uns64 timerBase; // nominal counter base value - - // SYSTEM AND BANKED REGISTERS (INFREQUENTLY USED AT RUN TIME) - armBankRegs bank; // banked registers - armSCSRegs scs; // SCS registers - - // VFP REGISTERS - armFPCW currentCW; // current control word - armArithFlags sdfpAFlags; // FPU comparison flags - Uns8 sdfpFlags; // FPU operation flags - Uns8 sdfpSticky; // FPU sticky flags - armVFPR vregs; // VFP data registers - - // VARIANT CONFIGURATION - Uns32 flags; // configuration flags - armConfig configInfo; // configuration register defaults - armCompatMode compatMode :2; // compatibility mode - Bool simEx :1; // simulate exceptions? - Bool verbose :1; // verbose messages enabled? - Bool showHiddenRegs :1; // show hidden registers in reg dump - Bool UAL :1; // disassemble using UAL syntax - Bool disableBitBand :1; // bit banding disabled - - // MEMORY SUBSYSTEM SUPPORT - Bool restoreDomain :1; // whether to resore domain (LDRT, STRT) - protRegionP impu; // instruction/unified MPU - protRegionP dmpu; // data MPU (if not unified) - armDomainSet ids; // instruction domain set - armDomainSet dds; // data domain set - - // NET HANDLES (used for NVIC) - Uns32 sysResetReq; // system reset requested - Uns32 intISS; // interrupt service started - Uns32 eventOut; // event output signal - Uns32 lockup; // lockup output signal - - // EXCEPTION SUPPORT - Int32 unboostedPriority; // unboosted execution priority - Int32 executionPriority; // current execution priority - armExceptNum enabledException; // current enabled exception - armExceptNum pendingException; // current pending exception - armExceptNum derivedException; // pushStack/popStack exception - Uns32 nestedActivation; // used for handler->thread check - Uns32 xPend[ARM_EXCEPT_MASK_NUM]; // pending exceptions - Uns32 xActive[ARM_EXCEPT_MASK_NUM];// active exceptions - Uns32 xEnable[ARM_EXCEPT_MASK_NUM];// exception enables - Uns8 xPriority[ARM_EXCEPT_NUM]; // exception priorities - vmiNetPortP netPorts; // net ports on this variant - memDomainP FPCARdomain; // memory domain associated with the FPCAR - - // INTERCEPT LIBRARY SUPPORT - armDecoderFn decoderCB; // generic instruction decoder - armIsizeFn isizeCB; // instruction size callback - -} arm; - - -#endif - diff --git a/simulators/ovp/armmModel/armSys.h b/simulators/ovp/armmModel/armSys.h deleted file mode 100644 index d488f76d..00000000 --- a/simulators/ovp/armmModel/armSys.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_SYS_H -#define ARM_SYS_H - -// VMI header files -#include "vmi/vmiTypes.h" - -// model header files -#include "armSysRegisters.h" -#include "armTypeRefs.h" - -// -// These are the bounds of the Peripheral region -// -#define PERIPH_LOW 0x40000000 -#define PERIPH_HIGH 0x4fffffff - -// -// These are the bounds of the System Control Space -// -#define DEVICE_LOW 0xa0000000 -#define DEVICE_HIGH 0xdfffffff - -// -// These are the bounds of the System Control Space -// -#define SYSTEM_LOW 0xe0000000 -#define SYSTEM_HIGH 0xffffffff - -// -// These are the bounds of the Private Peripheral Bus -// -#define PPB_LOW 0xe0000000 -#define PPB_HIGH 0xe00fffff - -// -// Call on initialization -// -void armSysInitialize(armP arm); - -// -// Call on reset -// -void armSysReset(armP arm); - -// -// Is the indicated system register supported on this processor? -// -Bool armGetSysRegSupported(armSCSRegId id, armP arm); - -// -// Perform a privileged-mode read of the system register -// -Bool armReadSysRegPriv(armSCSRegId id, armP arm, Uns32 *result); - -// -// Perform a privileged-mode write of the system register -// -Bool armWriteSysRegPriv(armSCSRegId id, armP arm, Uns32 value); - -// -// Add programmer's view of system register -// -void armAddSysRegisterView( - armSCSRegId id, - armP arm, - vmiViewObjectP baseObject, - const char *name -); - -// -// Structure filled with system register description by -// armGetSysRegisterDesc -// -typedef struct armSysRegDescS { - const char *name; - armSCSRegId id; - Uns32 address; - const char *privRW; - const char *userRW; -} armSysRegDesc, *armSysRegDescP; - -// -// Iterator filling 'desc' with the next system register description - -// 'desc.name' should be initialized to NULL prior to the first call -// -Bool armGetSysRegisterDesc(armSysRegDescP desc); - -// -// Insert SCS region into the passed domain at the standard location -// -void armSysCreateSCSRegion(armP arm, memDomainP domain); - -#endif - diff --git a/simulators/ovp/armmModel/armSysRegisters.h b/simulators/ovp/armmModel/armSysRegisters.h deleted file mode 100644 index f7c5d5d5..00000000 --- a/simulators/ovp/armmModel/armSysRegisters.h +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_SYS_REGISTERS_H -#define ARM_SYS_REGISTERS_H - -// model header files -#include "armRegisters.h" - - -// -// Implementor codes -// -typedef enum armImplementorE { - AI_ARM = 0x41, - AI_DEC = 0x44, - AI_INTEL = 0x69, -} armImplementor; - -// ----------------------------------------------------------------------------- -// SYSTEM REGISTERS -// ----------------------------------------------------------------------------- - -// construct enumeration member name from register name -#define SCS_ID(_R) SCS_ID_##_R - -// morph-time macro to access a field in a system register -#define ARM_SCS_REG(_ID) ARM_CPU_REG(scs.regs[_ID]) - -// access an entire system register as an Uns32 -#define SCS_REG_UNS32(_P, _R) ((_P)->scs.regs[SCS_ID(_R)]) - -// access an entire system register as a structure -#define SCS_REG_STRUCT(_P, _R) ((_P)->scs.fields._R) - -// access a field in a system register -#define SCS_FIELD(_P, _R, _F) SCS_REG_STRUCT(_P, _R)._F - -// get mask to use when writing a system register -#define SCS_MASK_UNS32(_P, _R) ((_P)->configInfo.regMasks._R.value32) - -// get mask to use when writing a system register -#define SCS_MASK_FIELD(_P, _R, _F) ((_P)->configInfo.regMasks._R.fields._F) - -// access default value for an entire system register as a structure -#define SCS_REG_STRUCT_DEFAULT(_P, _R) ((_P)->configInfo.regDefaults._R) - -// access default value for a field in a system register -#define SCS_FIELD_DEFAULT(_P, _R, _F) (SCS_REG_STRUCT_DEFAULT(_P, _R)._F) - -// should CPUID registers be used to determine feature presence? -#define SCS_USE_CPUID(_P) (SCS_FIELD(_P, CPUID, ARCHITECTURE)==0xf) - -// access to ID_ISAR field -#define ARM_ISAR(_N, _F) SCS_FIELD(arm, ID_ISAR##_N, _F) - - -// -// Identifiers for each implemented system register -// -typedef enum armSCSRegIdE { - - // this code defines an invalid system register specification - SCS_ID(INVALID)=-1, - - // system control register entries (represented in processor structure) - SCS_ID(ICTR), - SCS_ID(ACTLR), - SCS_ID(CPUID), - SCS_ID(VTOR), - SCS_ID(AIRCR), - SCS_ID(SCR), - SCS_ID(CCR), - SCS_ID(CFSR), - SCS_ID(HFSR), - SCS_ID(AFSR), - SCS_ID(MMAR), - SCS_ID(BFAR), - SCS_ID(CPACR), - - // timer control register entries (represented in processor structure) - SCS_ID(SYST_CSR), - SCS_ID(SYST_RVR), - SCS_ID(SYST_CVR), - SCS_ID(SYST_CALIB), - - // CPU Id register entries (represented in processor structure) - SCS_ID(ID_PFR0), - SCS_ID(ID_PFR1), - SCS_ID(ID_DFR0), - SCS_ID(ID_AFR0), - SCS_ID(ID_MMFR0), - SCS_ID(ID_MMFR1), - SCS_ID(ID_MMFR2), - SCS_ID(ID_MMFR3), - SCS_ID(ID_ISAR0), - SCS_ID(ID_ISAR1), - SCS_ID(ID_ISAR2), - SCS_ID(ID_ISAR3), - SCS_ID(ID_ISAR4), - SCS_ID(ID_ISAR5), - - // FP Registers (represented in processor structure) - SCS_ID(FPCCR), - SCS_ID(FPCAR), - SCS_ID(FPDSCR), - SCS_ID(MVFR0), - SCS_ID(MVFR1), - - // MPU control register entries (represented in processor structure) - SCS_ID(MPU_TYPE), - SCS_ID(MPU_CONTROL), - SCS_ID(MPU_RNR), - - // marker for pseudo-registers (not represented in processor structure) - SCS_ID(FirstPseudoReg), - - // system control register entries - SCS_ID(ICSR) = SCS_ID(FirstPseudoReg), - SCS_ID(SHCSR), - SCS_ID(SHPR1), - SCS_ID(SHPR2), - SCS_ID(SHPR3), - SCS_ID(STIR), - - // NVIC operations - SCS_ID(NVIC_ISERx16), - SCS_ID(NVIC_ICERx16), - SCS_ID(NVIC_ISPRx16), - SCS_ID(NVIC_ICPRx16), - SCS_ID(NVIC_IABRx16), - SCS_ID(NVIC_IPRx255), - - // MPU operations - SCS_ID(MPU_RBAR), - SCS_ID(MPU_RASR), - SCS_ID(MPU_RBAR_A1), - SCS_ID(MPU_RASR_A1), - SCS_ID(MPU_RBAR_A2), - SCS_ID(MPU_RASR_A2), - SCS_ID(MPU_RBAR_A3), - SCS_ID(MPU_RASR_A3), - - // keep last (used to define size of the enumeration) - SCS_ID(Size), - -} armSCSRegId; - -// use this to declare a register structure below -#define SCS_REG_STRUCT_DECL(_N) armSCSReg_##_N - - -// ----------------------------------------------------------------------------- -// ICTR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 INTLINESNUM : 4; - Uns32 _u1 : 28; -} SCS_REG_STRUCT_DECL(ICTR); - -#define SCS_WRITE_MASK_ICTR 0x00000000 -#define SCS_ADDRESS_ICTR 0x004 - -// ----------------------------------------------------------------------------- -// ACTLR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 value; -} SCS_REG_STRUCT_DECL(ACTLR); - -#define SCS_WRITE_MASK_ACTLR 0xffffffff -#define SCS_ADDRESS_ACTLR 0x008 - -// ----------------------------------------------------------------------------- -// CPUID -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 REVISION : 4; - Uns32 PARTNO : 12; - Uns32 ARCHITECTURE : 4; - Uns32 VARIANT : 4; - armImplementor IMPLEMENTER : 8; -} SCS_REG_STRUCT_DECL(CPUID); - -#define SCS_WRITE_MASK_CPUID 0x00000000 -#define SCS_ADDRESS_CPUID 0xd00 - -// ----------------------------------------------------------------------------- -// ICSR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 VECTACTIVE : 9; - Uns32 _u1 : 2; - Uns32 RETTOBASE : 1; - Uns32 VECTPENDING : 9; - Uns32 _u2 : 1; - Uns32 ISRPENDING : 1; - Uns32 ISRPREEMPT : 1; - Uns32 _u3 : 1; - Uns32 PENDSTCLR : 1; - Uns32 PENDSTSET : 1; - Uns32 PENDSVCLR : 1; - Uns32 PENDSVSET : 1; - Uns32 _u4 : 2; - Uns32 NMIPENDSET : 1; -} SCS_REG_STRUCT_DECL(ICSR); - -#define SCS_WRITE_MASK_ICSR 0xffffffff -#define SCS_ADDRESS_ICSR 0xd04 - -// ----------------------------------------------------------------------------- -// VTOR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 _u1 : 7; - Uns32 TBLOFF : 22; - Uns32 TBLBASE : 1; - Uns32 _u2 : 2; -} SCS_REG_STRUCT_DECL(VTOR); - -#define SCS_WRITE_MASK_VTOR 0x3fffff80 -#define SCS_ADDRESS_VTOR 0xd08 - -// ----------------------------------------------------------------------------- -// AIRCR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 VECTRESET : 1; // TODO: not implemented, debug feature - Uns32 VECTCLRACTIVE : 1; // TODO: not implemented, debug feature - Uns32 SYSRESETREQ : 1; - Uns32 _u1 : 5; - Uns32 PRIGROUP : 3; - Uns32 _u2 : 4; - Uns32 ENDIANNESS : 1; - Uns32 VECTKEY : 16; -} SCS_REG_STRUCT_DECL(AIRCR); - -#define SCS_WRITE_MASK_AIRCR 0xffff7fff -#define SCS_ADDRESS_AIRCR 0xd0c - -// ----------------------------------------------------------------------------- -// SCR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 _u1 : 1; - Uns32 SLEEPONEXIT : 1; - Uns32 SLEEPDEEP : 1; - Uns32 _u2 : 1; - Uns32 SEVONPEND : 1; - Uns32 _u3 : 27; -} SCS_REG_STRUCT_DECL(SCR); - -#define SCS_WRITE_MASK_SCR 0x00000016 -#define SCS_ADDRESS_SCR 0xd10 - -// ----------------------------------------------------------------------------- -// CCR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 NONBASETHRDENA : 1; - Uns32 USERSETMPEND : 1; - Uns32 _u1 : 1; - Uns32 UNALIGN_TRP : 1; - Uns32 DIV_0_TRP : 1; - Uns32 _u2 : 3; - Uns32 BFHFNMIGN : 1; - Uns32 STKALIGN : 1; - Uns32 _u3 : 22; -} SCS_REG_STRUCT_DECL(CCR); - -#define SCS_WRITE_MASK_CCR 0x0000031b -#define SCS_ADDRESS_CCR 0xd14 - -// ----------------------------------------------------------------------------- -// SHPR1 ... SHPR3 -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_SHPR1 0x00ffffff -#define SCS_ADDRESS_SHPR1 0xd18 -#define SCS_WRITE_MASK_SHPR2 0xff000000 -#define SCS_ADDRESS_SHPR2 0xd1c -#define SCS_WRITE_MASK_SHPR3 0xffff00ff -#define SCS_ADDRESS_SHPR3 0xd20 - -// ----------------------------------------------------------------------------- -// STIR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 INTID : 10; - Uns32 _u1 : 22; -} SCS_REG_STRUCT_DECL(STIR); - -#define SCS_WRITE_MASK_STIR 0xffffffff -#define SCS_ADDRESS_STIR 0xf00 - -// ----------------------------------------------------------------------------- -// NVIC_ISER0 ... NVIC_ISER15 -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_NVIC_ISER 0xffffffff -#define SCS_ADDRESS_NVIC_ISER 0x100 - -// ----------------------------------------------------------------------------- -// NVIC_ICER0 ... NVIC_ICER15 -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_NVIC_ICER 0xffffffff -#define SCS_ADDRESS_NVIC_ICER 0x180 - -// ----------------------------------------------------------------------------- -// NVIC_ISPR0 ... NVIC_ISPR15 -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_NVIC_ISPR 0xffffffff -#define SCS_ADDRESS_NVIC_ISPR 0x200 - -// ----------------------------------------------------------------------------- -// NVIC_ICPR0 ... NVIC_ICPR15 -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_NVIC_ICPR 0xffffffff -#define SCS_ADDRESS_NVIC_ICPR 0x280 - -// ----------------------------------------------------------------------------- -// NVIC_IABR0 ... NVIC_IABR15 -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_NVIC_IABR 0xffffffff -#define SCS_ADDRESS_NVIC_IABR 0x300 - -// ----------------------------------------------------------------------------- -// NVIC_IPR0 ... NVIC_IPR255 -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_NVIC_IPR 0xffffffff -#define SCS_ADDRESS_NVIC_IPR 0x400 - -// ----------------------------------------------------------------------------- -// SHCSR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 MEMFAULTACT : 1; - Uns32 BUSFAULTACT : 1; - Uns32 _u1 : 1; - Uns32 USGFAULTACT : 1; - Uns32 _u2 : 3; - Uns32 SVCALLACT : 1; - Uns32 MONITORACT : 1; - Uns32 _u3 : 1; - Uns32 PENDSVACT : 1; - Uns32 SYSTICKACT : 1; - Uns32 USGFAULTPENDED : 1; - Uns32 MEMFAULTPENDED : 1; - Uns32 BUSFAULTPENDED : 1; - Uns32 SVCALLPENDED : 1; - Uns32 MEMFAULTENA : 1; - Uns32 BUSFAULTENA : 1; - Uns32 USGFAULTENA : 1; - Uns32 _u4 : 13; -} SCS_REG_STRUCT_DECL(SHCSR); - -#define SCS_WRITE_MASK_SHCSR 0xffffffff -#define SCS_ADDRESS_SHCSR 0xd24 - -// ----------------------------------------------------------------------------- -// CFSR -// ----------------------------------------------------------------------------- - -typedef struct { - // MMFSR - Uns32 IACCVIOL : 1; - Uns32 DACCVIOL : 1; - Uns32 _u1 : 1; - Uns32 MUNSTKERR : 1; - Uns32 MSTKERR : 1; - Uns32 _u2 : 2; - Uns32 MMARVALID : 1; - // BFSR - Uns32 IBUSERR : 1; - Uns32 PRECISERR : 1; - Uns32 IMPRECISERR : 1; - Uns32 UNSTKERR : 1; - Uns32 STKERR : 1; - Uns32 _u3 : 2; - Uns32 BFARVALID : 1; - // UFSR - Uns32 UNDEFINSTR : 1; - Uns32 INVSTATE : 1; - Uns32 INVPC : 1; - Uns32 NOCP : 1; - Uns32 _u4 : 4; - Uns32 UNALIGNED : 1; - Uns32 DIVBYZERO : 1; - Uns32 _u5 : 6; -} SCS_REG_STRUCT_DECL(CFSR); - -#define SCS_WRITE_MASK_CFSR 0xffffffff -#define SCS_ADDRESS_CFSR 0xd28 - -// ----------------------------------------------------------------------------- -// HFSR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 _u1 : 1; - Uns32 VECTTBL : 1; - Uns32 _u2 : 28; - Uns32 FORCED : 1; - Uns32 DEBUGEVT : 1; -} SCS_REG_STRUCT_DECL(HFSR); - -#define SCS_WRITE_MASK_HFSR 0xffffffff -#define SCS_ADDRESS_HFSR 0xd2c - -// ----------------------------------------------------------------------------- -// AFSR -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_AFSR 0xffffffff -#define SCS_ADDRESS_AFSR 0xd3c - -// ----------------------------------------------------------------------------- -// MMAR -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_MMAR 0xffffffff -#define SCS_ADDRESS_MMAR 0xd34 - -// ----------------------------------------------------------------------------- -// BFAR -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_BFAR 0xffffffff -#define SCS_ADDRESS_BFAR 0xd38 - -// ----------------------------------------------------------------------------- -// CPACR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 cp0 : 2; - Uns32 cp1 : 2; - Uns32 cp2 : 2; - Uns32 cp3 : 2; - Uns32 cp4 : 2; - Uns32 cp5 : 2; - Uns32 cp6 : 2; - Uns32 cp7 : 2; - Uns32 _u1 : 4; - Uns32 cp10 : 2; - Uns32 cp11 : 2; - Uns32 _u2 : 8; -} SCS_REG_STRUCT_DECL(CPACR); - -#define SCS_WRITE_MASK_CPACR 0xffffffff /* Actual mask used is from config data */ -#define SCS_ADDRESS_CPACR 0xd88 - -// ----------------------------------------------------------------------------- -// SYST_CSR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 ENABLE : 1; - Uns32 TICKINT : 1; - Uns32 CLKSOURCE : 1; - Uns32 _u1 : 13; - Uns32 COUNTFLAG : 1; - Uns32 _u2 : 15; -} SCS_REG_STRUCT_DECL(SYST_CSR); - -#define SCS_WRITE_MASK_SYST_CSR 0x00000007 -#define SCS_ADDRESS_SYST_CSR 0x010 - -// ----------------------------------------------------------------------------- -// SYST_RVR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 RELOAD : 24; - Uns32 _u1 : 8; -} SCS_REG_STRUCT_DECL(SYST_RVR); - -#define SCS_WRITE_MASK_SYST_RVR 0x00ffffff -#define SCS_ADDRESS_SYST_RVR 0x014 - -// ----------------------------------------------------------------------------- -// SYST_CVR -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_SYST_CVR 0xffffffff -#define SCS_ADDRESS_SYST_CVR 0x018 - -// ----------------------------------------------------------------------------- -// SYST_CALIB -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 TENMS : 24; - Uns32 _u1 : 6; - Uns32 SKEW : 1; - Uns32 NOREF : 1; -} SCS_REG_STRUCT_DECL(SYST_CALIB); - -#define SCS_WRITE_MASK_SYST_CALIB 0x00000000 -#define SCS_ADDRESS_SYST_CALIB 0x01c - -// ----------------------------------------------------------------------------- -// ID_PFR0 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 State0 : 4; - Uns32 State1 : 4; - Uns32 State2 : 4; - Uns32 State3 : 4; - Uns32 _u1 : 16; -} SCS_REG_STRUCT_DECL(ID_PFR0); - -#define SCS_WRITE_MASK_ID_PFR0 0x00000000 -#define SCS_ADDRESS_ID_PFR0 0xd40 - -// ----------------------------------------------------------------------------- -// ID_PFR1 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 ProgrammersModel : 4; - Uns32 SecurityExtension : 4; - Uns32 MicroProgrammersModel : 4; - Uns32 _u1 : 20; -} SCS_REG_STRUCT_DECL(ID_PFR1); - -#define SCS_WRITE_MASK_ID_PFR1 0x00000000 -#define SCS_ADDRESS_ID_PFR1 0xd44 - -// ----------------------------------------------------------------------------- -// ID_DFR0 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 CoreDebug : 4; - Uns32 SecureDebug : 4; - Uns32 EmbeddedDebug : 4; - Uns32 TraceDebugCP : 4; - Uns32 TraceDebugMM : 4; - Uns32 MicroDebug : 4; - Uns32 _u1 : 8; -} SCS_REG_STRUCT_DECL(ID_DFR0); - -#define SCS_WRITE_MASK_ID_DFR0 0x00000000 -#define SCS_ADDRESS_ID_DFR0 0xd48 - -// ----------------------------------------------------------------------------- -// ID_AFR0 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 _u1 : 32; -} SCS_REG_STRUCT_DECL(ID_AFR0); - -#define SCS_WRITE_MASK_ID_AFR0 0x00000000 -#define SCS_ADDRESS_ID_AFR0 0xd4c - -// ----------------------------------------------------------------------------- -// ID_MMFR0 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 VMSA : 4; - Uns32 PMSA : 4; - Uns32 Cache_Agent : 4; - Uns32 Cache_DMA : 4; - Uns32 TCM_DMA : 4; - Uns32 AuxControl : 4; - Uns32 FCSE : 4; - Uns32 _u1 : 4; -} SCS_REG_STRUCT_DECL(ID_MMFR0); - -#define SCS_WRITE_MASK_ID_MMFR0 0x00000000 -#define SCS_ADDRESS_ID_MMFR0 0xd50 - -// ----------------------------------------------------------------------------- -// ID_MMFR1 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 L1VAHarvard : 4; - Uns32 L1VAUnified : 4; - Uns32 L1SWHarvard : 4; - Uns32 L1SWUnified : 4; - Uns32 L1Harvard : 4; - Uns32 L1Unified : 4; - Uns32 L1TestClean : 4; - Uns32 BTB : 4; -} SCS_REG_STRUCT_DECL(ID_MMFR1); - -#define SCS_WRITE_MASK_ID_MMFR1 0x00000000 -#define SCS_ADDRESS_ID_MMFR1 0xd54 - -// ----------------------------------------------------------------------------- -// ID_MMFR2 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 L1FgndPrefetchHarvard : 4; - Uns32 L1BgndPrefetchHarvard : 4; - Uns32 L1MaintRangeHarvard : 4; - Uns32 TLBMaintHarvard : 4; - Uns32 TLBMaintUnified : 4; - Uns32 MemoryBarrierCP15 : 4; - Uns32 WaitForInterruptStall : 4; - Uns32 HWAccessFlag : 4; -} SCS_REG_STRUCT_DECL(ID_MMFR2); - -#define SCS_WRITE_MASK_ID_MMFR2 0x00000000 -#define SCS_ADDRESS_ID_MMFR2 0xd58 - -// ----------------------------------------------------------------------------- -// ID_MMFR3 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 HierMaintSW : 4; - Uns32 HierMaintMVA : 4; - Uns32 BPMaint : 4; - Uns32 _u1 : 20; -} SCS_REG_STRUCT_DECL(ID_MMFR3); - -#define SCS_WRITE_MASK_ID_MMFR3 0x00000000 -#define SCS_ADDRESS_ID_MMFR3 0xd5c - -// ----------------------------------------------------------------------------- -// ID_ISAR0 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 Swap_instrs : 4; - Uns32 BitCount_instrs : 4; - Uns32 BitField_instrs : 4; - Uns32 CmpBranch_instrs : 4; - Uns32 Coproc_instrs : 4; - Uns32 Debug_instrs : 4; - Uns32 Divide_instrs : 4; - Uns32 _u1 : 4; -} SCS_REG_STRUCT_DECL(ID_ISAR0); - -#define SCS_WRITE_MASK_ID_ISAR0 0x00000000 -#define SCS_ADDRESS_ID_ISAR0 0xd60 - -// ----------------------------------------------------------------------------- -// ID_ISAR1 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 Endian_instrs : 4; - Uns32 Except_instrs : 4; - Uns32 Except_AR_instrs : 4; - Uns32 Extend_instrs : 4; - Uns32 IfThen_instrs : 4; - Uns32 Immediate_instrs : 4; - Uns32 Interwork_instrs : 4; - Uns32 Jazelle_instrs : 4; -} SCS_REG_STRUCT_DECL(ID_ISAR1); - -#define SCS_WRITE_MASK_ID_ISAR1 0x00000000 -#define SCS_ADDRESS_ID_ISAR1 0xd64 - -// ----------------------------------------------------------------------------- -// ID_ISAR2 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 LoadStore_instrs : 4; - Uns32 MemHint_instrs : 4; - Uns32 MultiAccessInt_instrs : 4; - Uns32 Mult_instrs : 4; - Uns32 MultS_instrs : 4; - Uns32 MultU_instrs : 4; - Uns32 PSR_AR_instrs : 4; - Uns32 Reversal_instrs : 4; -} SCS_REG_STRUCT_DECL(ID_ISAR2); - -#define SCS_WRITE_MASK_ID_ISAR2 0x00000000 -#define SCS_ADDRESS_ID_ISAR2 0xd68 - -// ----------------------------------------------------------------------------- -// ID_ISAR3 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 Saturate_instrs : 4; - Uns32 SIMD_instrs : 4; - Uns32 SVC_instrs : 4; - Uns32 SynchPrim_instrs : 4; - Uns32 TabBranch_instrs : 4; - Uns32 ThumbCopy_instrs : 4; - Uns32 TrueNOP_instrs : 4; - Uns32 T2ExeEnvExtn_instrs : 4; -} SCS_REG_STRUCT_DECL(ID_ISAR3); - -#define SCS_WRITE_MASK_ID_ISAR3 0x00000000 -#define SCS_ADDRESS_ID_ISAR3 0xd6c - -// ----------------------------------------------------------------------------- -// ID_ISAR4 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 Unpriv_instrs : 4; - Uns32 WithShifts_instrs : 4; - Uns32 Writeback_instrs : 4; - Uns32 SMI_instrs : 4; - Uns32 Barrier_instrs : 4; - Uns32 SynchPrim_instrs_frac : 4; - Uns32 PSR_M_instrs : 4; - Uns32 SWP_frac : 4; -} SCS_REG_STRUCT_DECL(ID_ISAR4); - -#define SCS_WRITE_MASK_ID_ISAR4 0x00000000 -#define SCS_ADDRESS_ID_ISAR4 0xd70 - -// ----------------------------------------------------------------------------- -// ID_ISAR5 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 _u1 : 32; -} SCS_REG_STRUCT_DECL(ID_ISAR5); - -#define SCS_WRITE_MASK_ID_ISAR5 0x00000000 -#define SCS_ADDRESS_ID_ISAR5 0xd74 - -// ----------------------------------------------------------------------------- -// FPCCR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 LSPACT : 1; // Blockmask bit - Uns32 USER : 1; - Uns32 _u1 : 1; - Uns32 THREAD : 1; - Uns32 HFRDY : 1; - Uns32 MMRDY : 1; - Uns32 BFRDY : 1; - Uns32 _u2 : 1; - Uns32 MONRDY : 1; - Uns32 _u3 : 21; - Uns32 LSPEN : 1; - Uns32 ASPEN : 1; // Blockmask bit -} SCS_REG_STRUCT_DECL(FPCCR); - -#define SCS_WRITE_MASK_FPCCR 0xc000017b -#define SCS_ADDRESS_FPCCR 0xf34 - -// Bits in FPCCR that are part of the block mask -#define SCS_BLOCKMASK_FPCCR 0x80000001 - -// ----------------------------------------------------------------------------- -// FPCAR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 _u1 : 3; - Uns32 ADDRESS : 29; -} SCS_REG_STRUCT_DECL(FPCAR); - -#define SCS_WRITE_MASK_FPCAR 0xfffffff8 -#define SCS_ADDRESS_FPCAR 0xf38 - -// ----------------------------------------------------------------------------- -// FPDSCR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 _u1 : 22; - Uns32 RMode : 2; - Uns32 FZ : 1; - Uns32 DN : 1; - Uns32 AHP : 1; - Uns32 _u2 : 5; -} SCS_REG_STRUCT_DECL(FPDSCR); - -#define SCS_WRITE_MASK_FPDSCR 0x07c00000 -#define SCS_ADDRESS_FPDSCR 0xf3c - -// ----------------------------------------------------------------------------- -// MVFR0 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 A_SIMD_Registers : 4; - Uns32 SinglePrecision : 4; - Uns32 DoublePrecision : 4; - Uns32 VFP_ExceptionTrap : 4; - Uns32 Divide : 4; - Uns32 SquareRoot : 4; - Uns32 ShortVectors : 4; - Uns32 VFP_RoundingModes : 4; -} SCS_REG_STRUCT_DECL(MVFR0); - -#define SCS_WRITE_MASK_MVFR0 0x00000000 -#define SCS_ADDRESS_MVFR0 0xf40 - -// ----------------------------------------------------------------------------- -// MVFR1 -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 FlushToZeroMode : 4; - Uns32 DefaultNaNMode : 4; - Uns32 _u1 : 16; - Uns32 VFP_HalfPrecision : 4; - Uns32 VFP_FusedMAC : 4; -} SCS_REG_STRUCT_DECL(MVFR1); - -#define SCS_WRITE_MASK_MVFR1 0x00000000 -#define SCS_ADDRESS_MVFR1 0xf44 - -// ----------------------------------------------------------------------------- -// MPU_TYPE -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 SEPARATE : 1; - Uns32 _u1 : 7; - Uns32 DREGION : 8; - Uns32 IREGION : 8; - Uns32 _u2 : 8; -} SCS_REG_STRUCT_DECL(MPU_TYPE); - -#define SCS_WRITE_MASK_MPU_TYPE 0x00000000 -#define SCS_ADDRESS_MPU_TYPE 0xd90 - -// ----------------------------------------------------------------------------- -// MPU_CONTROL -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 ENABLE : 1; - Uns32 HFNMIENA : 1; - Uns32 PRIVDEFENA : 1; - Uns32 _u1 : 29; -} SCS_REG_STRUCT_DECL(MPU_CONTROL); - -#define SCS_WRITE_MASK_MPU_CONTROL 0x00000007 -#define SCS_ADDRESS_MPU_CONTROL 0xd94 - -// ----------------------------------------------------------------------------- -// MPU_RNR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 REGION : 8; - Uns32 _u1 : 24; -} SCS_REG_STRUCT_DECL(MPU_RNR); - -#define SCS_WRITE_MASK_MPU_RNR 0x000000ff -#define SCS_ADDRESS_MPU_RNR 0xd98 - -// ----------------------------------------------------------------------------- -// MPU_RBAR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 REGION : 4; - Uns32 VALID : 1; - Uns32 ADDR : 27; -} SCS_REG_STRUCT_DECL(MPU_RBAR), - SCS_REG_STRUCT_DECL(MPU_RBAR_A1), - SCS_REG_STRUCT_DECL(MPU_RBAR_A2), - SCS_REG_STRUCT_DECL(MPU_RBAR_A3); - -#define SCS_MASK_MPU_RBAR_ADDR 0xffffffe0 -#define SCS_WRITE_MASK_MPU_RBAR 0xffffffff -#define SCS_WRITE_MASK_MPU_RBAR_A1 0xffffffff -#define SCS_WRITE_MASK_MPU_RBAR_A2 0xffffffff -#define SCS_WRITE_MASK_MPU_RBAR_A3 0xffffffff -#define SCS_ADDRESS_MPU_RBAR 0xd9c -#define SCS_ADDRESS_MPU_RBAR_A1 0xda4 -#define SCS_ADDRESS_MPU_RBAR_A2 0xdac -#define SCS_ADDRESS_MPU_RBAR_A3 0xdb4 - -// ----------------------------------------------------------------------------- -// MPU_RASR -// ----------------------------------------------------------------------------- - -typedef struct { - Uns32 ENABLE : 1; - Uns32 SIZE : 5; - Uns32 _u1 : 2; - Uns32 SRD : 8; - Uns32 B : 1; - Uns32 C : 1; - Uns32 S : 1; - Uns32 TEX : 3; - Uns32 _u2 : 2; - Uns32 AP : 3; - Uns32 _u3 : 1; - Uns32 XN : 1; - Uns32 _u4 : 3; -} SCS_REG_STRUCT_DECL(MPU_RASR), - SCS_REG_STRUCT_DECL(MPU_RASR_A1), - SCS_REG_STRUCT_DECL(MPU_RASR_A2), - SCS_REG_STRUCT_DECL(MPU_RASR_A3); - -#define SCS_WRITE_MASK_MPU_RASR 0xffffffff -#define SCS_WRITE_MASK_MPU_RASR_A1 0xffffffff -#define SCS_WRITE_MASK_MPU_RASR_A2 0xffffffff -#define SCS_WRITE_MASK_MPU_RASR_A3 0xffffffff -#define SCS_ADDRESS_MPU_RASR 0xda0 -#define SCS_ADDRESS_MPU_RASR_A1 0xda8 -#define SCS_ADDRESS_MPU_RASR_A2 0xdb0 -#define SCS_ADDRESS_MPU_RASR_A3 0xdb8 - - -// ----------------------------------------------------------------------------- -// IGNORED OPERATION WRITE MASK -// ----------------------------------------------------------------------------- - -#define SCS_WRITE_MASK_Ignored 0x00000000 - - -// ----------------------------------------------------------------------------- -// CONTAINER -// ----------------------------------------------------------------------------- - -// use this to define a field-based register entry in armSCSRegsU below -#define SCS_REG_DECL(_N) SCS_REG_STRUCT_DECL(_N) _N - -// use this to define a plain register entry in armSCSRegsU below -#define SCS_UNS32_DECL(_N) Uns32 _N - -// -// This type defines the entire implemented system register set -// -typedef union armSCSRegsU { - - Uns32 regs[SCS_ID(FirstPseudoReg)]; // use this for by-register access - - struct { // use this for by-field access - // system register entries - SCS_REG_DECL(ICTR); - SCS_UNS32_DECL(ACTLR); - SCS_REG_DECL(CPUID); - SCS_REG_DECL(VTOR); - SCS_REG_DECL(AIRCR); - SCS_REG_DECL(SCR); - SCS_REG_DECL(CCR); - SCS_REG_DECL(CFSR); - SCS_REG_DECL(HFSR); - SCS_UNS32_DECL(AFSR); - SCS_UNS32_DECL(MMAR); - SCS_UNS32_DECL(BFAR); - SCS_REG_DECL(CPACR); - SCS_REG_DECL(SYST_CSR); - SCS_REG_DECL(SYST_RVR); - SCS_UNS32_DECL(SYST_CVR); - SCS_REG_DECL(SYST_CALIB); - SCS_REG_DECL(ID_PFR0); - SCS_REG_DECL(ID_PFR1); - SCS_REG_DECL(ID_DFR0); - SCS_REG_DECL(ID_AFR0); - SCS_REG_DECL(ID_MMFR0); - SCS_REG_DECL(ID_MMFR1); - SCS_REG_DECL(ID_MMFR2); - SCS_REG_DECL(ID_MMFR3); - SCS_REG_DECL(ID_ISAR0); - SCS_REG_DECL(ID_ISAR1); - SCS_REG_DECL(ID_ISAR2); - SCS_REG_DECL(ID_ISAR3); - SCS_REG_DECL(ID_ISAR4); - SCS_REG_DECL(ID_ISAR5); - SCS_REG_DECL(FPCCR); - SCS_REG_DECL(FPCAR); - SCS_REG_DECL(FPDSCR); - SCS_REG_DECL(MVFR0); - SCS_REG_DECL(MVFR1); - SCS_REG_DECL(MPU_TYPE); - SCS_REG_DECL(MPU_CONTROL); - SCS_REG_DECL(MPU_RNR); - } fields; - -} armSCSRegs, *armSCSRegsP; - -#endif diff --git a/simulators/ovp/armmModel/armTypeRefs.h b/simulators/ovp/armmModel/armTypeRefs.h deleted file mode 100644 index 871c7dcb..00000000 --- a/simulators/ovp/armmModel/armTypeRefs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_TYPEREFS_H -#define ARM_TYPEREFS_H - -// VMI header files -#include "hostapi/typeMacros.h" - -DEFINE_S(arm); -DEFINE_S(armInstructionInfo); -DEFINE_S(armMorphState); -DEFINE_CS(armMorphAttr); - -#endif diff --git a/simulators/ovp/armmModel/armUtils.h b/simulators/ovp/armmModel/armUtils.h deleted file mode 100644 index 2a9419f5..00000000 --- a/simulators/ovp/armmModel/armUtils.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_UTILS_H -#define ARM_UTILS_H - -// model header files -#include "armTypeRefs.h" - -// -// Set the initial endianness for the model -// -void armSetInitialEndian(armP arm, Bool isBigEndian); - -// -// Return the name of a GPR -// -const char *armGetGPRName(armP arm, Uns32 index); - -// -// Return the name of a CPR -// -const char *armGetCPRName(armP arm, Uns32 index); - -// -// Update processor block mask -// -void armSetBlockMask(armP arm); - -// -// Switch banked registers on switch to the passed mode -// -void armSwitchRegs(armP arm, Bool oldUseSPProcess, Bool newUseSPProcess); - -// -// Write CONTROL.SP_PROCESS field -// -void armWriteSPProcess(armP arm, Bool newSPProcess); - -// -// Read CPSR register -// -Uns32 armReadCPSR(armP arm); - -// -// Write CPSR register -// -void armWriteCPSR(armP arm, Uns32 value, Uns32 mask); - -// -// Write PRIMASK register -// -void armWritePRIMASK(armP arm, Uns32 value); - -// -// Write BASEPRI register -// -void armWriteBASEPRI(armP arm, Uns32 value); - -// -// Write BASEPRI register (using BASEPRI_MAX semantics) -// -void armWriteBASEPRI_MAX(armP arm, Uns32 value); - -// -// Write FAULTMASK register -// -void armWriteFAULTMASK(armP arm, Uns32 value); - -// -// read CONTROL register -// -Uns32 armReadCONTROL(armP arm); - -// -// Write CONTROL register -// -void armWriteCONTROL(armP arm, Uns32 value); - -// -// update the CONTROL.FPCA bit to the value. If it changes then set the block mask -// -void armUpdateFPCA(armP arm, Bool value); - -// -// update the FPCCR.LSPACT bit to the value. If it changes then set the block mask -// -void armUpdateLSPACT(armP arm, Bool value); - -// -// Write SP register -// -void armWriteSP(armP arm, Uns32 value); - -// -// Switch processor mode if required -// -void armSwitchMode(armP arm); - -// -// Abort any active exclusive access -// -void armAbortExclusiveAccess(armP arm); - -#endif diff --git a/simulators/ovp/armmModel/armVFP.h b/simulators/ovp/armmModel/armVFP.h deleted file mode 100644 index 4d0605ca..00000000 --- a/simulators/ovp/armmModel/armVFP.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_SIMD_VFP_H -#define ARM_SIMD_VFP_H - -// VMI header files -#include "vmi/vmiTypes.h" - -// model header files -#include "armTypeRefs.h" - -// -// Write VFP FPSCR register -// -void armWriteFPSCR(armP arm, Uns32 newValue, Uns32 writeMask); - -// -// Read VFP FPSCR register -// -Uns32 armReadFPSCR(armP arm); - -// -// Call on initialization -// -void armFPInitialize(armP arm); - -// -// Call on reset -// -void armFPReset(armP arm); - -// -// Convert from half-precision to single-precision -// -Uns32 armFPHalfToSingle(armP arm, Uns16 half); - -// -// Convert from single-precision to half-precision -// -Uns16 armFPSingleToHalf(armP arm, Uns32 single); - -// -// Return True if the single-precision floating point values op1 and op2 are 0 -// and infinity (in either order), setting the denormal sticky bit if so -// -Bool armFPInfinityAndZero(armP arm, Uns32 op1, Uns32 op2); - -#endif diff --git a/simulators/ovp/armmModel/armVM.h b/simulators/ovp/armmModel/armVM.h deleted file mode 100644 index 80b4a24e..00000000 --- a/simulators/ovp/armmModel/armVM.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_VM_H -#define ARM_VM_H - -// VMI header files -#include "vmi/vmiTypes.h" - -// model header files -#include "armTypeRefs.h" - - -// -// This is the minimum page size (1Kb) -// -#define MIN_PAGE_SIZE 1024 - -// -// Enumation describing actions performed by armVMMiss -// -typedef enum armVMActionE { - MA_OK, // memory was mapped, access can proceed - MA_EXCEPTION // memory was not mapped, exception was triggered -} armVMAction; - -// -// Try mapping memory at the passed address for the specified access type and -// return a status code indicating whether the mapping succeeded -// -armVMAction armVMMiss( - armP arm, - memPriv requiredPriv, - Uns32 address, - Uns32 bytes, - memAccessAttrs attrs -); - -// -// Set the privileged mode data domain to the user domain (for LDRT, STRT) -// -void armVMSetUserPrivilegedModeDataDomain(armP arm); - -// -// Restore the normal data domain for the current mode (for LDRT, STRT) -// -void armVMRestoreNormalDataDomain(armP arm); - -// -// Write the indexed MPU RBAR register value -// -void armVMWriteRBAR(armP arm, Uns32 index, Bool isData, Uns32 newValue); - -// -// Read the indexed MPU RBAR register value -// -Uns32 armVMReadRBAR(armP arm, Uns32 index, Bool isData); - -// -// Write the indexed MPU RASR register value -// -void armVMWriteRASR(armP arm, Uns32 index, Bool isData, Uns32 newValue); - -// -// Read the indexed MPU RASR register value -// -Uns32 armVMReadRASR(armP arm, Uns32 index, Bool isData); - -// -// Flush the privileged mode MPU -// -void armVMFlushMPUPriv(armP arm); - -// -// Reset VM structures -// -void armVMReset(armP arm); - -// -// Free structures used for virtual memory management -// -void armVMFree(armP arm); - -#endif - diff --git a/simulators/ovp/armmModel/armVariant.h b/simulators/ovp/armmModel/armVariant.h deleted file mode 100644 index 1541e5de..00000000 --- a/simulators/ovp/armmModel/armVariant.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARM_VARIANT_H -#define ARM_VARIANT_H - -// this defines the architecture options and variants -typedef enum armArchitectureE { - - // ARCHITECTURE OPTIONS - ARM_VM = 0x0010, // enable long multiply instructions - ARM_VT = 0x0020, // enable thumb instructions - ARM_VD = 0x0040, // enable basic DSP instructions - ARM_VD2 = 0x0080, // enable LDRD, MCRR, MRRC, PLD and STRD insns - ARM_SS = 0x0100, // enable supersections, TEX and S bits - ARM_BX = 0x0200, // enable BX instruction - ARM_J = 0x0400, // enable trivial Jazelle extension - ARM_K = 0x0800, // enable multi-processing instructions - ARM_VT2 = 0x1000, // enable Thumb-2 instructions - - // ARCHITECTURE VERSIONS - ARM_V4XM = 4, - ARM_V4 = 4 | ARM_VM, - ARM_V4TXM = 4 | ARM_BX | ARM_VT, - ARM_V4T = 4 | ARM_BX | ARM_VM | ARM_VT, - ARM_V5XM = 5 | ARM_BX, - ARM_V5 = 5 | ARM_BX | ARM_VM, - ARM_V5TXM = 5 | ARM_BX | ARM_VT, - ARM_V5T = 5 | ARM_BX | ARM_VM | ARM_VT, - ARM_V5TEXP = 5 | ARM_BX | ARM_VM | ARM_VT | ARM_VD, - ARM_V5TE = 5 | ARM_BX | ARM_VM | ARM_VT | ARM_VD | ARM_VD2 | ARM_SS, - ARM_V5TEJ = 5 | ARM_BX | ARM_VM | ARM_VT | ARM_VD | ARM_VD2 | ARM_SS | ARM_J, - ARM_V6 = 6 | ARM_BX | ARM_VM | ARM_VT | ARM_VD | ARM_VD2 | ARM_SS | ARM_J, - ARM_V6K = 6 | ARM_BX | ARM_VM | ARM_VT | ARM_VD | ARM_VD2 | ARM_SS | ARM_J | ARM_K, - ARM_V6T2 = 6 | ARM_BX | ARM_VM | ARM_VT | ARM_VD | ARM_VD2 | ARM_SS | ARM_J | ARM_VT2, - ARM_V7 = 7 | ARM_BX | ARM_VM | ARM_VT | ARM_VD | ARM_VD2 | ARM_SS | ARM_J | ARM_K | ARM_VT2 - -} armArchitecture; - -// this defines thumb versions -typedef enum armThumbVersionE { - ARM_THUMB_NONE, // no thumb instructions - ARM_THUMB_V1, // version 1 thumb instructions - ARM_THUMB_V2 // version 2 thumb instructions -} armThumbVersion; - -// this selects armArchitecture bits specifying instruction version -#define ARM_MASK_VERSION 0xf - -// this is used to restrict availability of features to certain variants -#define ARM_SUPPORT(_V, _M) (((_V) & (_M)) == (_M)) - -// get the main instruction set version -#define ARM_INSTRUCTION_VERSION(_V) ((_V) & ARM_MASK_VERSION) - -// get the thumb instruction set version -#define ARM_THUMB_VERSION(_V) ( \ - !ARM_SUPPORT(_V, ARM_VT) ? ARM_THUMB_NONE : \ - (ARM_INSTRUCTION_VERSION(_V)==4) ? ARM_THUMB_V1 : ARM_THUMB_V2 \ -) - -// get architecture index for the passed variant -#define ARM_VARIANT_ARCH(_V) \ - ({ \ - Uns32 _IV = ARM_INSTRUCTION_VERSION(_V); \ - (_IV>=7) ? 0xf : \ - (_IV==6) ? 0x7 : \ - (_IV==5) && ((_V)&ARM_J) ? 0x6 : \ - (_IV==5) && ((_V)&ARM_VD2) ? 0x5 : \ - (_IV==5) && ((_V)&ARM_VT) ? 0x4 : \ - (_IV==5) ? 0x3 : \ - (_IV==4) && ((_V)&ARM_VT) ? 0x2 : \ - (_IV==4) ? 0x1 : 0x0; \ - }) - -#endif diff --git a/simulators/ovp/armmModel/armmAttrs.c b/simulators/ovp/armmModel/armmAttrs.c deleted file mode 100644 index 0d322bb4..00000000 --- a/simulators/ovp/armmModel/armmAttrs.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiAttrs.h" - -// model header files -#include "armStructure.h" -#include "armFunctions.h" - -static const char *dictNames[] = {"PRIV", "USER", "PRIV_MPU", "USER_MPU", "ARM", 0}; - -// -// Configuration block for instruction-accurate modelling -// -const vmiIASAttr modelAttrs = { - - //////////////////////////////////////////////////////////////////////// - // VERSION & SIZE ATTRIBUTES - //////////////////////////////////////////////////////////////////////// - - .versionString = VMI_VERSION, - .modelType = VMI_PROCESSOR_MODEL, - .dictNames = dictNames, - .cpuSize = sizeof(arm), - - //////////////////////////////////////////////////////////////////////// - // CREATE/DELETE ROUTINES - //////////////////////////////////////////////////////////////////////// - - .constructorCB = armConstructor, - .vmInitCB = armVMInit, - .destructorCB = armDestructor, - - //////////////////////////////////////////////////////////////////////// - // MORPHER CORE ROUTINES - //////////////////////////////////////////////////////////////////////// - - .morphCB = armMorphInstruction, - .fetchSnapCB = armFetchSnap, - - //////////////////////////////////////////////////////////////////////// - // SIMULATION SUPPORT ROUTINES - //////////////////////////////////////////////////////////////////////// - - .getEndianCB = armGetEndian, - .nextPCCB = armNextInstruction, - .disCB = armDisassemble, - .switchCB = armContextSwitchCB, - - //////////////////////////////////////////////////////////////////////// - // EXCEPTION ROUTINES - //////////////////////////////////////////////////////////////////////// - - .rdPrivExceptCB = armRdPrivExceptionCB, - .wrPrivExceptCB = armWrPrivExceptionCB, - .rdAlignExceptCB = armRdAlignExceptionCB, - .wrAlignExceptCB = armWrAlignExceptionCB, - .rdAbortExceptCB = armRdAbortExceptionCB, - .wrAbortExceptCB = armWrAbortExceptionCB, - .arithExceptCB = armArithExceptionCB, - .ifetchExceptCB = armIFetchExceptionCB, - .icountExceptCB = armICountPendingCB, - - //////////////////////////////////////////////////////////////////////// - // DEBUGGER INTEGRATION SUPPORT ROUTINES - //////////////////////////////////////////////////////////////////////// - - .regGroupCB = armRegGroup, - .regInfoCB = armRegInfo, - .exceptionInfoCB = armExceptionInfo, - .modeInfoCB = armModeInfo, - .getExceptionCB = armGetException, - .getModeCB = armGetMode, - .debugCB = armDumpRegisters, - - //////////////////////////////////////////////////////////////////////// - // PARAMETER SUPPORT ROUTINES - //////////////////////////////////////////////////////////////////////// - - .paramSpecsCB = armGetParamSpec, - .paramValueSizeCB = armParamValueSize, - - //////////////////////////////////////////////////////////////////////// - // PORT ROUTINES - //////////////////////////////////////////////////////////////////////// - - .busPortSpecsCB = armGetBusPortSpec, - .netPortSpecsCB = armGetNetPortSpec, - - //////////////////////////////////////////////////////////////////////// - // IMPERAS INTERCEPTED FUNCTION SUPPORT ROUTINES - //////////////////////////////////////////////////////////////////////// - - .intReturnCB = armIntReturnCB, - .intResultCB = armIntResultCB, - .intParCB = armIntParCB, - - //////////////////////////////////////////////////////////////////////// - // PROCESSOR INFO ROUTINE - //////////////////////////////////////////////////////////////////////// - - .procInfoCB = armProcInfo, -}; diff --git a/simulators/ovp/armmModel/armmConfigList.c b/simulators/ovp/armmModel/armmConfigList.c deleted file mode 100644 index 70b50386..00000000 --- a/simulators/ovp/armmModel/armmConfigList.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// model header files -#include "armConfig.h" -#include "armVariant.h" - -const struct armConfigS armConfigTable[] = { - - //////////////////////////////////////////////////////////////////////////// - // ISA CONFIGURATIONS - //////////////////////////////////////////////////////////////////////////// - - {.name = "ARMv7-M", .arch = ARM_V7, .rotateUnaligned = True}, - - //////////////////////////////////////////////////////////////////////////// - // PROCESSOR MODEL CONFIGURATIONS - //////////////////////////////////////////////////////////////////////////// - - { - .name = "Cortex-M3", - .arch = ARM_V7, - .numInterrupts = 16, - .rotateUnaligned = False, - .align64as32 = True, // ARMv7-M has no 64-bit load/stores - .STRoffsetPC12 = False, // required value for ARMv7 on - .priorityBitsM1 = 2, // number of priority bits (minus 1) - - .regDefaults = { - .CPUID = { - .REVISION = 0, - .PARTNO = 0xc23, - .ARCHITECTURE = 0xf, - .VARIANT = 0x2, - .IMPLEMENTER = AI_ARM - }, - .ID_PFR0 = { - .State0 = 0, // 32-bit ARM instruction set support - .State1 = 3, // Thumb encoding support - .State2 = 0, // Jazelle support - .State3 = 0 // ThumbEE support - }, - .ID_PFR1 = { - .ProgrammersModel = 0, // ARM programmer's model - .SecurityExtension = 0, // Security Extensions support - .MicroProgrammersModel = 2 // Microcontroller programmer's model - }, - .ID_DFR0 = { - .CoreDebug = 0, // Core debug model - .SecureDebug = 0, // Secure debug model - .EmbeddedDebug = 0, // Embedded debug model - .TraceDebugCP = 0, // Trace debug model, coprocessor-based - .TraceDebugMM = 0, // Trace debug model, memory mapped - .MicroDebug = 0, // Microcontroller debug model - }, - .ID_MMFR0 = { - .VMSA = 0, // VMSA support - .PMSA = 3, // PMSA support - .Cache_Agent = 0, // Cache coherency + CPU agent - .Cache_DMA = 0, // Cache coherency + associated DMA - .TCM_DMA = 0, // TCM + associated DMA - .AuxControl = 0, // ARMv6 Auxillary Control register - .FCSE = 0, // FCSE support - }, - .ID_MMFR1 = { - .L1VAHarvard = 0, // L1 maintainence by VA, Harvard - .L1VAUnified = 0, // L1 maintainence by VA, unified - .L1SWHarvard = 0, // L1 maintainence by Set/Way, Harvard - .L1SWUnified = 0, // L1 maintainence by Set/Way, unified - .L1Harvard = 0, // L1 maintainence, Harvard - .L1Unified = 0, // L1 maintainence, unified - .L1TestClean = 0, // L1 test and clean - .BTB = 0 // Branch target buffer - }, - .ID_MMFR2 = { - .L1FgndPrefetchHarvard = 0, // L1 F/ground cache p/fetch range, Harvard - .L1BgndPrefetchHarvard = 0, // L1 B/ground cache p/fetch range, Harvard - .L1MaintRangeHarvard = 0, // L1 maintanence range, Harvard - .TLBMaintHarvard = 0, // TLB maintanence, Harvard - .TLBMaintUnified = 0, // TLB maintanence, Unified - .MemoryBarrierCP15 = 0, // Memory Barrier, CP15 based - .WaitForInterruptStall = 0, // Wait-for-interrupt stalling - .HWAccessFlag = 0 // hardware access flag support - }, - .ID_MMFR3 = { - .HierMaintSW = 0, // Hierarchical cache maintainence, set/way - .HierMaintMVA = 0, // Hierarchical cache maintainence, MVA - .BPMaint = 0, // Branch predictor maintainence - }, - .ID_ISAR0 = { - .Swap_instrs = 0, // Atomic instructions - .BitCount_instrs = 1, // BitCount instructions - .BitField_instrs = 1, // BitField instructions - .CmpBranch_instrs = 1, // CmpBranch instructions - .Coproc_instrs = 4, // Coprocessor instructions - .Debug_instrs = 1, // Debug instructions - .Divide_instrs = 1, // Divide instructions - }, - .ID_ISAR1 = { - .Endian_instrs = 0, // Endian instructions - .Except_instrs = 0, // Exception instructions - .Except_AR_instrs = 0, // A/R profile exception instructions - .Extend_instrs = 1, // Extend instructions - .IfThen_instrs = 1, // IfThen instructions - .Immediate_instrs = 1, // Immediate instructions - .Interwork_instrs = 2, // Interwork instructions - .Jazelle_instrs = 0 // Jazelle instructions - }, - .ID_ISAR2 = { - .LoadStore_instrs = 1, // LoadStore instructions - .MemHint_instrs = 3, // MemoryHint instructions - .MultiAccessInt_instrs = 2, // Multi-access interruptible instructions - .Mult_instrs = 2, // Multiply instructions - .MultS_instrs = 1, // Multiply instructions, advanced signed - .MultU_instrs = 1, // Multiply instructions, advanced unsigned - .PSR_AR_instrs = 1, // A/R profile PSR instructions - .Reversal_instrs = 2 // Reversal instructions - }, - .ID_ISAR3 = { - .Saturate_instrs = 0, // Saturate instructions - .SIMD_instrs = 1, // SIMD instructions - .SVC_instrs = 1, // SVC instructions - .SynchPrim_instrs = 1, // SynchPrim instructions - .TabBranch_instrs = 1, // TableBranch instructions - .ThumbCopy_instrs = 1, // ThumbCopy instructions - .TrueNOP_instrs = 1, // TrueNOP instructions - .T2ExeEnvExtn_instrs = 0 // Thumb-2 Execution env extensions - }, - .ID_ISAR4 = { - .Unpriv_instrs = 2, // Unprivileged instructions - .WithShifts_instrs = 0, // Shift instructions - .Writeback_instrs = 1, // Writeback instructions - .SMI_instrs = 0, // SMI instructions - .Barrier_instrs = 1, // Barrier instructions - .SynchPrim_instrs_frac = 3, // Fractional support for sync primitive instructions - .PSR_M_instrs = 1, // M-profile forms of PSR instructions - .SWP_frac = 0 // memory system bus locking - }, - .ICTR = { - .INTLINESNUM = 0 // number of interrupt lines supported - }, - .ACTLR = {0}, // auxillary control register - .MPU_TYPE = { - .SEPARATE = 0, // unified MPU - .DREGION = 8, // number of data/unified memory regions - .IREGION = 0 // number of instruction memory regions - }, - .SYST_CALIB = { - .NOREF = 0, // reference clock provided - .SKEW = 0, // whether calibration value inexact - .TENMS = 0 // 10ms reload value - } - }, - - .regMasks = { - } - }, - - { - .name = "Cortex-M4", - .arch = ARM_V7, - .numInterrupts = 16, - .rotateUnaligned = False, - .align64as32 = True, // ARMv7-M has no 64-bit load/stores - .STRoffsetPC12 = False, // required value for ARMv7 on - .priorityBitsM1 = 2, // number of priority bits (minus 1) - - .regDefaults = { - .CPUID = { - .REVISION = 1, - .PARTNO = 0xc24, - .ARCHITECTURE = 0xf, - .VARIANT = 0x0, - .IMPLEMENTER = AI_ARM - }, - .ID_PFR0 = { - .State0 = 0, // 32-bit ARM instruction set support - .State1 = 3, // Thumb encoding support - .State2 = 0, // Jazelle support - .State3 = 0 // ThumbEE support - }, - .ID_PFR1 = { - .ProgrammersModel = 0, // ARM programmer's model - .SecurityExtension = 0, // Security Extensions support - .MicroProgrammersModel = 2 // Microcontroller programmer's model - }, - .ID_DFR0 = { - .CoreDebug = 0, // Core debug model - .SecureDebug = 0, // Secure debug model - .EmbeddedDebug = 0, // Embedded debug model - .TraceDebugCP = 0, // Trace debug model, coprocessor-based - .TraceDebugMM = 0, // Trace debug model, memory mapped - .MicroDebug = 0, // Microcontroller debug model - }, - .ID_MMFR0 = { - .VMSA = 0, // VMSA support - .PMSA = 3, // PMSA support - .Cache_Agent = 0, // Cache coherency + CPU agent - .Cache_DMA = 0, // Cache coherency + associated DMA - .TCM_DMA = 0, // TCM + associated DMA - .AuxControl = 0, // ARMv6 Auxillary Control register - .FCSE = 0, // FCSE support - }, - .ID_MMFR1 = { - .L1VAHarvard = 0, // L1 maintainence by VA, Harvard - .L1VAUnified = 0, // L1 maintainence by VA, unified - .L1SWHarvard = 0, // L1 maintainence by Set/Way, Harvard - .L1SWUnified = 0, // L1 maintainence by Set/Way, unified - .L1Harvard = 0, // L1 maintainence, Harvard - .L1Unified = 0, // L1 maintainence, unified - .L1TestClean = 0, // L1 test and clean - .BTB = 0 // Branch target buffer - }, - .ID_MMFR2 = { - .L1FgndPrefetchHarvard = 0, // L1 F/ground cache p/fetch range, Harvard - .L1BgndPrefetchHarvard = 0, // L1 B/ground cache p/fetch range, Harvard - .L1MaintRangeHarvard = 0, // L1 maintanence range, Harvard - .TLBMaintHarvard = 0, // TLB maintanence, Harvard - .TLBMaintUnified = 0, // TLB maintanence, Unified - .MemoryBarrierCP15 = 0, // Memory Barrier, CP15 based - .WaitForInterruptStall = 0, // Wait-for-interrupt stalling - .HWAccessFlag = 0 // hardware access flag support - }, - .ID_MMFR3 = { - .HierMaintSW = 0, // Hierarchical cache maintainence, set/way - .HierMaintMVA = 0, // Hierarchical cache maintainence, MVA - .BPMaint = 0, // Branch predictor maintainence - }, - .ID_ISAR0 = { - .Swap_instrs = 0, // Atomic instructions - .BitCount_instrs = 1, // BitCount instructions - .BitField_instrs = 1, // BitField instructions - .CmpBranch_instrs = 1, // CmpBranch instructions - .Coproc_instrs = 4, // Coprocessor instructions - .Debug_instrs = 1, // Debug instructions - .Divide_instrs = 1, // Divide instructions - }, - .ID_ISAR1 = { - .Endian_instrs = 0, // Endian instructions - .Except_instrs = 0, // Exception instructions - .Except_AR_instrs = 0, // A/R profile exception instructions - .Extend_instrs = 2, // Extend instructions - .IfThen_instrs = 1, // IfThen instructions - .Immediate_instrs = 1, // Immediate instructions - .Interwork_instrs = 2, // Interwork instructions - .Jazelle_instrs = 0 // Jazelle instructions - }, - .ID_ISAR2 = { - .LoadStore_instrs = 1, // LoadStore instructions - .MemHint_instrs = 3, // MemoryHint instructions - .MultiAccessInt_instrs = 2, // Multi-access interruptible instructions - .Mult_instrs = 2, // Multiply instructions - .MultS_instrs = 3, // Multiply instructions, advanced signed - .MultU_instrs = 2, // Multiply instructions, advanced unsigned - .PSR_AR_instrs = 1, // A/R profile PSR instructions - .Reversal_instrs = 2 // Reversal instructions - }, - .ID_ISAR3 = { - .Saturate_instrs = 1, // Saturate instructions - .SIMD_instrs = 3, // SIMD instructions - .SVC_instrs = 1, // SVC instructions - .SynchPrim_instrs = 1, // SynchPrim instructions - .TabBranch_instrs = 1, // TableBranch instructions - .ThumbCopy_instrs = 1, // ThumbCopy instructions - .TrueNOP_instrs = 1, // TrueNOP instructions - .T2ExeEnvExtn_instrs = 0 // Thumb-2 Execution env extensions - }, - .ID_ISAR4 = { - .Unpriv_instrs = 2, // Unprivileged instructions - .WithShifts_instrs = 3, // Shift instructions - .Writeback_instrs = 1, // Writeback instructions - .SMI_instrs = 0, // SMI instructions - .Barrier_instrs = 1, // Barrier instructions - .SynchPrim_instrs_frac = 3, // Fractional support for sync primitive instructions - .PSR_M_instrs = 1, // M-profile forms of PSR instructions - .SWP_frac = 0 // memory system bus locking - }, - .ICTR = { - .INTLINESNUM = 0 // number of interrupt lines supported - }, - .ACTLR = {0}, // auxillary control register - .MPU_TYPE = { - .SEPARATE = 0, // unified MPU - .DREGION = 8, // number of data/unified memory regions - .IREGION = 0 // number of instruction memory regions - }, - .SYST_CALIB = { - .NOREF = 0, // reference clock provided - .SKEW = 0, // whether calibration value inexact - .TENMS = 0 // 10ms reload value - }, - }, - - .regMasks = { - } - }, - - { - .name = "Cortex-M4F", - .arch = ARM_V7, - .numInterrupts = 16, - .rotateUnaligned = False, - .align64as32 = True, // ARMv7-M has no 64-bit load/stores - .STRoffsetPC12 = False, // required value for ARMv7 on - .priorityBitsM1 = 2, // number of priority bits (minus 1) - - .regDefaults = { - .CPUID = { - .REVISION = 1, - .PARTNO = 0xc24, - .ARCHITECTURE = 0xf, - .VARIANT = 0x0, - .IMPLEMENTER = AI_ARM - }, - .ID_PFR0 = { - .State0 = 0, // 32-bit ARM instruction set support - .State1 = 3, // Thumb encoding support - .State2 = 0, // Jazelle support - .State3 = 0 // ThumbEE support - }, - .ID_PFR1 = { - .ProgrammersModel = 0, // ARM programmer's model - .SecurityExtension = 0, // Security Extensions support - .MicroProgrammersModel = 2 // Microcontroller programmer's model - }, - .ID_DFR0 = { - .CoreDebug = 0, // Core debug model - .SecureDebug = 0, // Secure debug model - .EmbeddedDebug = 0, // Embedded debug model - .TraceDebugCP = 0, // Trace debug model, coprocessor-based - .TraceDebugMM = 0, // Trace debug model, memory mapped - .MicroDebug = 0, // Microcontroller debug model - }, - .ID_MMFR0 = { - .VMSA = 0, // VMSA support - .PMSA = 3, // PMSA support - .Cache_Agent = 0, // Cache coherency + CPU agent - .Cache_DMA = 0, // Cache coherency + associated DMA - .TCM_DMA = 0, // TCM + associated DMA - .AuxControl = 0, // ARMv6 Auxillary Control register - .FCSE = 0, // FCSE support - }, - .ID_MMFR1 = { - .L1VAHarvard = 0, // L1 maintainence by VA, Harvard - .L1VAUnified = 0, // L1 maintainence by VA, unified - .L1SWHarvard = 0, // L1 maintainence by Set/Way, Harvard - .L1SWUnified = 0, // L1 maintainence by Set/Way, unified - .L1Harvard = 0, // L1 maintainence, Harvard - .L1Unified = 0, // L1 maintainence, unified - .L1TestClean = 0, // L1 test and clean - .BTB = 0 // Branch target buffer - }, - .ID_MMFR2 = { - .L1FgndPrefetchHarvard = 0, // L1 F/ground cache p/fetch range, Harvard - .L1BgndPrefetchHarvard = 0, // L1 B/ground cache p/fetch range, Harvard - .L1MaintRangeHarvard = 0, // L1 maintanence range, Harvard - .TLBMaintHarvard = 0, // TLB maintanence, Harvard - .TLBMaintUnified = 0, // TLB maintanence, Unified - .MemoryBarrierCP15 = 0, // Memory Barrier, CP15 based - .WaitForInterruptStall = 0, // Wait-for-interrupt stalling - .HWAccessFlag = 0 // hardware access flag support - }, - .ID_MMFR3 = { - .HierMaintSW = 0, // Hierarchical cache maintainence, set/way - .HierMaintMVA = 0, // Hierarchical cache maintainence, MVA - .BPMaint = 0, // Branch predictor maintainence - }, - .ID_ISAR0 = { - .Swap_instrs = 0, // Atomic instructions - .BitCount_instrs = 1, // BitCount instructions - .BitField_instrs = 1, // BitField instructions - .CmpBranch_instrs = 1, // CmpBranch instructions - .Coproc_instrs = 4, // Coprocessor instructions - .Debug_instrs = 1, // Debug instructions - .Divide_instrs = 1, // Divide instructions - }, - .ID_ISAR1 = { - .Endian_instrs = 0, // Endian instructions - .Except_instrs = 0, // Exception instructions - .Except_AR_instrs = 0, // A/R profile exception instructions - .Extend_instrs = 2, // Extend instructions - .IfThen_instrs = 1, // IfThen instructions - .Immediate_instrs = 1, // Immediate instructions - .Interwork_instrs = 2, // Interwork instructions - .Jazelle_instrs = 0 // Jazelle instructions - }, - .ID_ISAR2 = { - .LoadStore_instrs = 1, // LoadStore instructions - .MemHint_instrs = 3, // MemoryHint instructions - .MultiAccessInt_instrs = 2, // Multi-access interruptible instructions - .Mult_instrs = 2, // Multiply instructions - .MultS_instrs = 3, // Multiply instructions, advanced signed - .MultU_instrs = 2, // Multiply instructions, advanced unsigned - .PSR_AR_instrs = 1, // A/R profile PSR instructions - .Reversal_instrs = 2 // Reversal instructions - }, - .ID_ISAR3 = { - .Saturate_instrs = 1, // Saturate instructions - .SIMD_instrs = 3, // SIMD instructions - .SVC_instrs = 1, // SVC instructions - .SynchPrim_instrs = 1, // SynchPrim instructions - .TabBranch_instrs = 1, // TableBranch instructions - .ThumbCopy_instrs = 1, // ThumbCopy instructions - .TrueNOP_instrs = 1, // TrueNOP instructions - .T2ExeEnvExtn_instrs = 0 // Thumb-2 Execution env extensions - }, - .ID_ISAR4 = { - .Unpriv_instrs = 2, // Unprivileged instructions - .WithShifts_instrs = 3, // Shift instructions - .Writeback_instrs = 1, // Writeback instructions - .SMI_instrs = 0, // SMI instructions - .Barrier_instrs = 1, // Barrier instructions - .SynchPrim_instrs_frac = 3, // Fractional support for sync primitive instructions - .PSR_M_instrs = 1, // M-profile forms of PSR instructions - .SWP_frac = 0 // memory system bus locking - }, - .ICTR = { - .INTLINESNUM = 0 // number of interrupt lines supported - }, - .ACTLR = {0}, // auxillary control register - .MPU_TYPE = { - .SEPARATE = 0, // unified MPU - .DREGION = 8, // number of data/unified memory regions - .IREGION = 0 // number of instruction memory regions - }, - .SYST_CALIB = { - .NOREF = 0, // reference clock provided - .SKEW = 0, // whether calibration value inexact - .TENMS = 0 // 10ms reload value - }, - .MVFR0 = { - .A_SIMD_Registers = 1, // 16x64-bit media register bank - .SinglePrecision = 2, // single precision supported - .DoublePrecision = 0, // double precision not supported - .VFP_ExceptionTrap = 0, // trapped exceptions not supported - .Divide = 1, // VFP hardware divide supported - .SquareRoot = 1, // VFP hardware square root supported - .ShortVectors = 0, // VFP short vector not supported - .VFP_RoundingModes = 1 // all VFP rounding modes supported - }, - .MVFR1 = { - .FlushToZeroMode = 1, // VFP denormal arithmetic supported - .DefaultNaNMode = 1, // VFP NaN propagation supported - .VFP_HalfPrecision = 1, // VFP half-precision not supported - .VFP_FusedMAC = 1, // Fused multiply accumulate supported - } - }, - - .regMasks = { - } - }, - - - // null terminator - {0} -}; - diff --git a/simulators/ovp/armmModel/armmDebug.c b/simulators/ovp/armmModel/armmDebug.c deleted file mode 100644 index 11e8edb0..00000000 --- a/simulators/ovp/armmModel/armmDebug.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// Standard header files -#include "string.h" -#include "stdio.h" - -// Imperas header files -#include "hostapi/impAlloc.h" - -// VMI header files -#include "vmi/vmiAttrs.h" -#include "vmi/vmiDbg.h" -#include "vmi/vmiMessage.h" -#include "vmi/vmiOSLib.h" -#include "vmi/vmiRt.h" - -// model header files -#include "armRegisters.h" -#include "armStructure.h" -#include "armUtils.h" -#include "armSys.h" -#include "armVFP.h" - - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_DEBUG" - - -//////////////////////////////////////////////////////////////////////////////// -// REGISTER GROUPS -//////////////////////////////////////////////////////////////////////////////// - -// -// This describes the register groups in the processor -// -typedef enum armRegGroupIdE { - ARM_RG_CORE, // Core group - ARM_RG_CONTROL, // control register group - ARM_RG_SYSTEM, // memory-mapped system register group - ARM_RG_FPR, // VFP register group - ARM_RG_LAST // KEEP LAST: for sizing -} armRegGroupId; - -// -// This provides information about each group -// -static const vmiRegGroup groups[ARM_RG_LAST+1] = { - [ARM_RG_CORE] = {name: "Core" }, - [ARM_RG_CONTROL] = {name: "Control"}, - [ARM_RG_SYSTEM] = {name: "System" }, - [ARM_RG_FPR] = {name: "VFP" }, -}; - -// -// Macro to specify a the group for a register -// -#define ARM_GROUP(_G) &groups[ARM_RG_##_G] - - -//////////////////////////////////////////////////////////////////////////////// -// MACROS FOR REGISTER ACCESS -//////////////////////////////////////////////////////////////////////////////// - -// -// Macro to specify a register that can be accessed using raw read/write -// callbacks -// -#define ARM_RAW_REG(_R, _G) \ - VMI_REG_RAW_READ_CB, \ - VMI_REG_RAW_WRITE_CB, \ - (void *)ARM_CPU_OFFSET(_R), \ - _G - -// -// Core registers -// -#define ARM_CORE_REG(_I) ARM_RAW_REG(regs[_I], ARM_GROUP(CORE)) - -// -// Macro to specify the PC accessible for read/write -// -#define ARM_PC_RW readPC, writePC, 0, ARM_GROUP(CORE) - -// -// Macro to specify access for the stack pointer register -// -#define ARM_SP_REG(_R) \ - VMI_REG_RAW_READ_CB, \ - writeSP, \ - (void *)ARM_CPU_OFFSET(regs[_R]), \ - ARM_GROUP(CORE) - -// -// Macro to specify the control registers -// -#define ARM_CONTROL_RW(_ID) read##_ID, write##_ID, 0, ARM_GROUP(CONTROL) - -// -// Some registers are hidden in gdb, but we allow access to them -// -#define ARM_GDB_HIDDEN_INDEX 99 -#define IS_GDB_HIDDEN_REG(_I) ((_I)>=ARM_GDB_HIDDEN_INDEX) - -// -// system registers do not have access -// -#define ARM_CP_INDEX 0x1000 -#define IS_SCS_REG(_I) ((_I)>=ARM_CP_INDEX) - -// -// VFP registers - must check for existence in the variant -// -#define ARM_FPSCR_INDEX 24 -#define ARM_VFP0_INDEX 700 -#define ARM_VFP15_INDEX 715 -#define IS_VFP_REG(_I) ((_I)==ARM_FPSCR_INDEX || IS_VFP_DATA_REG(_I)) -#define IS_VFP_DATA_REG(_I) (((_I)>=ARM_VFP0_INDEX) && ((_I)<=ARM_VFP15_INDEX)) -#define ARM_VFP_INDEX(_I) ((_I)-ARM_VFP0_INDEX) -#define ARM_VFP_DATA_REG(_I) ARM_RAW_REG(vregs.d[_I], ARM_GROUP(FPR)) - -//////////////////////////////////////////////////////////////////////////////// -// DEBUGGER REGISTER INTERFACE -//////////////////////////////////////////////////////////////////////////////// - -// -// Return current vmiRegInfoCP structure for the passed banked vmiRegInfoCP -// -vmiRegInfoCP getCurrentInfo(vmiRegInfoCP reg); - -// -// Return system register id for vmiRegInfoCP -// -static armSCSRegId getSysId(vmiRegInfoCP reg) { - if(!IS_SCS_REG(reg->gdbIndex)) { - return SCS_ID(INVALID); - } else { - return (armSCSRegId)reg->userData; - } -} - -// -// Write callback for sp -// -static VMI_REG_WRITE_FN(writeSP) { - armWriteSP((armP)processor, *(Uns32*)buffer); - return True; -} - -// -// Read callback for pc -// -static VMI_REG_READ_FN(readPC) { - *(Uns32*)buffer = ((Uns32)vmirtGetPC(processor)); - return True; -} - -// -// Write callback for pc -// -static VMI_REG_WRITE_FN(writePC) { - Uns32 simPC = *(Uns32*)buffer; - vmirtSetPC(processor, simPC & ~1); - return True; -} - -// -// Read callback for PSR -// -static VMI_REG_READ_FN(readPSR) { - *(Uns32*)buffer = armReadCPSR((armP)processor); - return True; -} - -// -// Write callback for PSR -// -static VMI_REG_WRITE_FN(writePSR) { - armP arm = (armP)processor; - armWriteCPSR(arm, *(Uns32*)buffer, PSR_ALL); - return True; -} - -// -// Read callback for FPSCR -// -static VMI_REG_READ_FN(readFPSCR) { - *(Uns32*)buffer = armReadFPSCR((armP)processor); - return True; -} - -// -// Write callback for FPSCR -// -static VMI_REG_WRITE_FN(writeFPSCR) { - armP arm = (armP)processor; - armWriteFPSCR(arm, *(Uns32*)buffer, FPSCR_MASK); - return True; -} - -// -// Read callback for CONTROL -// -static VMI_REG_READ_FN(readControl) { - *(Uns32*)buffer = armReadCONTROL((armP)processor); - return True; -} - -// -// Write callback for CONTROL -// -static VMI_REG_WRITE_FN(writeControl) { - armP arm = (armP)processor; - armWriteCONTROL(arm, *(Uns32*)buffer); - return True; -} - -// -// Read callback for PRIMASK -// -static VMI_REG_READ_FN(readPRIMASK) { - armP arm = (armP)processor; - *(Uns32*)buffer = arm->sregs.PRIMASK; - return True; -} - -// -// Write callback for PRIMASK -// -static VMI_REG_WRITE_FN(writePRIMASK) { - armP arm = (armP)processor; - armWritePRIMASK(arm, *(Uns32*)buffer); - return True; -} - - -// -// Read callback for FAULTMASK -// -static VMI_REG_READ_FN(readFAULTMASK) { - armP arm = (armP)processor; - *(Uns32*)buffer = arm->sregs.FAULTMASK; - return True; -} -// -// Write callback for FAULTMASK -// -static VMI_REG_WRITE_FN(writeFAULTMASK) { - armP arm = (armP)processor; - armWriteFAULTMASK(arm, *(Uns32*)buffer); - return True; -} - -// -// Read callback for FAULTMASK -// -static VMI_REG_READ_FN(readBASEPRI) { - armP arm = (armP)processor; - *(Uns32*)buffer = arm->sregs.BASEPRI; - return True; -} - -// -// Write callback for BASEPRI -// -static VMI_REG_WRITE_FN(writeBASEPRI) { - armP arm = (armP)processor; - armWriteBASEPRI(arm, *(Uns32*)buffer); - return True; -} - -// -// Read callback for banked register -// -static VMI_REG_READ_FN(readBank) { - - armP arm = (armP)processor; - Bool trueUseSPProcess = USE_SP_PROCESS(arm); - Bool tempUseSPProcess = True; - - armSwitchRegs(arm, trueUseSPProcess, tempUseSPProcess); - Bool result = vmiosRegRead(processor, getCurrentInfo(reg), buffer); - armSwitchRegs(arm, tempUseSPProcess, trueUseSPProcess); - - return result; -} - -// -// Write callback for banked register -// -static VMI_REG_WRITE_FN(writeBank) { - - armP arm = (armP)processor; - Bool trueUseSPProcess = USE_SP_PROCESS(arm); - Bool tempUseSPProcess = True; - - armSwitchRegs(arm, trueUseSPProcess, tempUseSPProcess); - Bool result = vmiosRegWrite(processor, getCurrentInfo(reg), buffer); - armSwitchRegs(arm, tempUseSPProcess, trueUseSPProcess); - - return result; -} - -// -// Read callback for system register -// -static VMI_REG_READ_FN(readSCS) { - - armP arm = (armP)processor; - armSCSRegId id = getSysId(reg); - - if(!armReadSysRegPriv(id, arm, (Uns32*)buffer)) { - - return False; - - } else if(id!=SCS_ID(CPUID)) { - - return True; - - } else { - - union {Uns32 u32; SCS_REG_DECL(CPUID);} u = {*(Uns32*)buffer}; - - if(!u.u32) { - armArchitecture variant = arm->configInfo.arch; - u.CPUID.ARCHITECTURE = ARM_VARIANT_ARCH(variant); - *(Uns32*)buffer = u.u32; - } - - return True; - } -} - -// -// Write callback for system register -// -static VMI_REG_WRITE_FN(writeSCS) { - return armWriteSysRegPriv(getSysId(reg), (armP)processor, *(Uns32*)buffer); -} - -// -// Static const array holding information about the registers in the cpu, -// used for debugger interaction -// -static const vmiRegInfo basicRegisters[] = { - - // current mode registers (visible in gdb) - {"r0", 0, vmi_REG_NONE, 32, False, ARM_CORE_REG(0) }, - {"r1", 1, vmi_REG_NONE, 32, False, ARM_CORE_REG(1) }, - {"r2", 2, vmi_REG_NONE, 32, False, ARM_CORE_REG(2) }, - {"r3", 3, vmi_REG_NONE, 32, False, ARM_CORE_REG(3) }, - {"r4", 4, vmi_REG_NONE, 32, False, ARM_CORE_REG(4) }, - {"r5", 5, vmi_REG_NONE, 32, False, ARM_CORE_REG(5) }, - {"r6", 6, vmi_REG_NONE, 32, False, ARM_CORE_REG(6) }, - {"r7", 7, vmi_REG_NONE, 32, False, ARM_CORE_REG(7) }, - {"r8", 8, vmi_REG_NONE, 32, False, ARM_CORE_REG(8) }, - {"r9", 9, vmi_REG_NONE, 32, False, ARM_CORE_REG(9) }, - {"r10", 10, vmi_REG_NONE, 32, False, ARM_CORE_REG(10) }, - {"r11", 11, vmi_REG_FP, 32, False, ARM_CORE_REG(11) }, - {"r12", 12, vmi_REG_NONE, 32, False, ARM_CORE_REG(12) }, - {"sp", 13, vmi_REG_SP, 32, False, ARM_SP_REG (13) }, - {"lr", 14, vmi_REG_NONE, 32, False, ARM_CORE_REG(14) }, - {"pc", 15, vmi_REG_PC, 32, False, ARM_PC_RW }, - {"fps", 24, vmi_REG_NONE, 32, False, ARM_CONTROL_RW(FPSCR) }, - {"cpsr", 25, vmi_REG_NONE, 32, False, ARM_CONTROL_RW(PSR) }, - - // control and SP_process (not visible in gdb) - {"control", 100, vmi_REG_NONE, 32, False, ARM_CONTROL_RW(Control)}, - {"primask", 101, vmi_REG_NONE, 32, False, ARM_CONTROL_RW(PRIMASK)}, - {"faultmask", 102, vmi_REG_NONE, 32, False, ARM_CONTROL_RW(FAULTMASK)}, - {"basepri", 103, vmi_REG_NONE, 32, False, ARM_CONTROL_RW(BASEPRI)}, - {"sp_process", 113, vmi_REG_SP, 32, False, ARM_CONTROL_RW(Bank) }, - - // VFP registers - double word view only (not visible in gdb) - {"d0", 700, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(0) }, - {"d1", 701, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(1) }, - {"d2", 702, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(2) }, - {"d3", 703, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(3) }, - {"d4", 704, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(4) }, - {"d5", 705, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(5) }, - {"d6", 706, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(6) }, - {"d7", 707, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(7) }, - {"d8", 708, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(8) }, - {"d9", 709, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(9) }, - {"d10", 710, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(10)}, - {"d11", 711, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(11)}, - {"d12", 712, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(12)}, - {"d13", 713, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(13)}, - {"d14", 714, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(14)}, - {"d15", 715, vmi_REG_NONE, 64, False, ARM_VFP_DATA_REG(15)}, - - {0}, -}; - -// -// Return ARM register descriptions -// -static vmiRegInfoCP getRegisters(void) { - - static vmiRegInfo *allRegisters; - - if(!allRegisters) { - - armSysRegDesc desc; - Uns32 basicNum = 0; - Uns32 sysNum = 0; - Uns32 i; - - // count basic registers - while(basicRegisters[basicNum].name) { - basicNum++; - } - - // count system registers - desc.name = 0; - while(armGetSysRegisterDesc(&desc)) { - sysNum++; - } - - // allocate full register information, including terminating NULL entry - // TODO: This is never freed! Need to free description too - allRegisters = STYPE_CALLOC_N(vmiRegInfo, basicNum+sysNum+1); - - // fill basic entries - for(i=0; iname = desc.name; - reg->usage = vmi_REG_NONE; - reg->bits = 32; - reg->readonly = False; - reg->readCB = readSCS; - reg->writeCB = writeSCS; - reg->userData = (void *)desc.id; - reg->group = ARM_GROUP(SYSTEM); - - // synthesize a description - char descStr[64]; - snprintf(descStr, 64, "Addr: 0x%08x Priv:%s User:%s", desc.address, desc.privRW, desc.userRW); - reg->description = strdup(descStr); - - // use address as gdb pseudo-index - reg->gdbIndex = desc.address; - } - } - - // return register set - return allRegisters; -} - -// -// Return current vmiRegInfoCP structure for the passed banked vmiRegInfoCP -// -vmiRegInfoCP getCurrentInfo(vmiRegInfoCP reg) { - - Uns32 index = reg->gdbIndex % 100; - vmiRegInfoCP info; - - for(info=getRegisters(); info->name; info++) { - if(info->gdbIndex == index) { - return info; - } - } - - return 0; -} - -// -// Is the passed register supported on this processor? -// -static Bool isRegSupported(armP arm, vmiRegInfoCP reg, Bool gdbFrame) { - - if(gdbFrame && IS_GDB_HIDDEN_REG(reg->gdbIndex)) { - - // if this is a GDB frame request then registers that should be hidden - // from GDB should be ignored - return False; - - } else if(IS_VFP_REG(reg->gdbIndex)) { - - // VFP registers are supported if in variant - return FPU_PRESENT(arm); - - } else if(IS_SCS_REG(reg->gdbIndex)) { - - // system registers are supported only if the associated unit is present - return armGetSysRegSupported(getSysId(reg), arm); - - } - - // other registers are always supported - return True; - -} - -// -// Return next supported register on this processor -// -static vmiRegInfoCP getNextRegister(armP arm, vmiRegInfoCP reg, Bool gdbFrame) { - - do { - if(!reg) { - reg = getRegisters(); - } else if((reg+1)->name) { - reg = reg+1; - } else { - reg = 0; - } - } while(reg && !isRegSupported(arm, reg, gdbFrame)); - - return reg; -} - -// -// Is the passed register group supported on this processor? -// -static Bool isGroupSupported(armP arm, vmiRegGroupCP group) { - - vmiRegInfoCP info = 0; - - while((info=getNextRegister(arm, info, False))) { - if(info->group == group) { - return True; - } - } - - return False; -} - -// -// Return next supported group on this processor -// -static vmiRegGroupCP getNextGroup(armP arm, vmiRegGroupCP group) { - - do { - if(!group) { - group = groups; - } else if((group+1)->name) { - group = group+1; - } else { - group = 0; - } - } while(group && !isGroupSupported(arm, group)); - - return group; -} - -// -// Register structure iterator -// -VMI_REG_INFO_FN(armRegInfo) { - return getNextRegister((armP)processor, prev, gdbFrame); -} - -// -// Register group iterator -// -VMI_REG_GROUP_FN(armRegGroup) { - return getNextGroup((armP)processor, prev); -} - - -//////////////////////////////////////////////////////////////////////////////// -// REGISTER DUMP INTERFACE -//////////////////////////////////////////////////////////////////////////////// - -// -// Dump processor registers -// -VMI_DEBUG_FN(armDumpRegisters) { - - armP arm = (armP)processor; - Bool showHiddenRegs = arm->showHiddenRegs; - Uns32 nameWidth = showHiddenRegs ? 10 : 7; - vmiRegInfoCP info = 0; - - while((info=getNextRegister(arm, info, False))) { - - if(IS_SCS_REG(info->gdbIndex)) { - - // ignore system registers - - } else if(IS_VFP_DATA_REG(info->gdbIndex)) { - - // print VFP regs if enabled - if(ARM_DUMP_SDFP_REG(arm)) { - - const char *fmt = " %-*s 0x" FMT_640Nx "\n"; - Uns64 value; - - // read and print register value - vmiosRegRead(processor, info, &value); - vmiPrintf(fmt, nameWidth, info->name, value); - } - - } else if(!IS_GDB_HIDDEN_REG(info->gdbIndex) || showHiddenRegs) { - - const char *fmt; - Uns32 value; - - // read register value - vmiosRegRead(processor, info, &value); - - // select approriate format string - if((info->usage==vmi_REG_SP) || (info->usage==vmi_REG_PC)) { - fmt = " %-*s 0x%-8x 0x%x\n"; - } else { - fmt = " %-*s 0x%-8x %u\n"; - } - - // print register using selected format - vmiPrintf(fmt, nameWidth, info->name, value, value); - } - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// SCS PROGRAMMER'S VIEW -//////////////////////////////////////////////////////////////////////////////// - -// -// Add programmer's view of all system registers -// -void armAddSysRegistersView(armP arm, vmiViewObjectP processorObject) { - - vmiRegInfoCP info = 0; - - // create coprocessor 15 child object - vmiViewObjectP baseObject = vmirtAddViewObject(processorObject, "SCS", 0); - - while((info=getNextRegister(arm, info, False))) { - - if(IS_SCS_REG(info->gdbIndex)) { - - const char *name = info->name; - armSCSRegId id = getSysId(info); - - armAddSysRegisterView(id, arm, baseObject, name); - } - } -} - diff --git a/simulators/ovp/armmModel/armmDecode.c b/simulators/ovp/armmModel/armmDecode.c deleted file mode 100644 index dfe3d8df..00000000 --- a/simulators/ovp/armmModel/armmDecode.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiMessage.h" - -// model header files -#include "armDecodeThumb.h" -#include "armDecodeTypes.h" -#include "armStructure.h" - - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_DECODE" - - -// -// Decode the instruction at the passed address. The 'info' structure is filled -// with details of the instruction. -// -ARM_DECODER_FN(armDecode) { - - // record current PC in decoded structure - info->thisPC = thisPC; - - // do decode (Thumb mode only) - armDecodeThumb(arm, thisPC, info); -} - -// -// Return the size of the instruction at the passed address and the mode -// -ARM_ISIZE_FN(armGetInstructionSizeMode) { - return isThumb ? armGetThumbInstructionSize(arm, thisPC) : 4; -} - -// -// Return the size of the instruction at the passed address -// -Uns32 armGetInstructionSize(armP arm, Uns32 thisPC) { - return armGetInstructionSizeMode(arm, thisPC, IN_THUMB_MODE(arm)); -} - diff --git a/simulators/ovp/armmModel/armmDecodeThumb.c b/simulators/ovp/armmModel/armmDecodeThumb.c deleted file mode 100644 index 2b65b58b..00000000 --- a/simulators/ovp/armmModel/armmDecodeThumb.c +++ /dev/null @@ -1,2725 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiCxt.h" -#include "vmi/vmiDecode.h" -#include "vmi/vmiMessage.h" -#include "vmi/vmiRt.h" - -// model header files -#include "armAttributeEntriesThumb16.h" -#include "armAttributeEntriesThumb32.h" -#include "armBitMacros.h" -#include "armDecode.h" -#include "armDecodeEntriesThumb16.h" -#include "armDecodeEntriesThumb32.h" -#include "armDecodeThumb.h" -#include "armRegisters.h" -#include "armStructure.h" -#include "armSysRegisters.h" -#include "armVariant.h" - - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_DECODE_THUMB" - - -//////////////////////////////////////////////////////////////////////////////// -// THUMB INSTRUCTION TYPES -//////////////////////////////////////////////////////////////////////////////// - -// -// Decode entries for 32-bit Thumb instructions like LDR -// -#define TT32_SET_LDR(_NAME) \ - TT32_##_NAME##_IMM1, \ - TT32_##_NAME##_IMM2, \ - TT32_##_NAME##_IMM3, \ - TT32_##_NAME##_RM, \ - TT32_##_NAME##_RM_SHFT_IMM, \ - TT32_##_NAME##T_IMM - -// -// Decode entries for 32-bit Thumb instructions like PLD -// -#define TT32_SET_PLD(_NAME) \ - TT32_##_NAME##_IMM1, \ - TT32_##_NAME##_IMM2, \ - TT32_##_NAME##_IMM3, \ - TT32_##_NAME##_RM, \ - TT32_##_NAME##_RM_SHFT_IMM - -// -// Decode entries for 32-bit Thumb instructions like ADD -// -#define TT32_SET_ADD(_NAME) \ - TT32_##_NAME##_IMM, \ - TT32_##_NAME##_RM_SHFT_IMM, \ - TT32_##_NAME##_RM_RRX - -// -// Instruction types for 32-bit Thumb parallel add/subtract Media instructions -// -#define TT32_SET_PAS(_NAME) \ - TT32_S##_NAME, \ - TT32_Q##_NAME, \ - TT32_SH##_NAME, \ - TT32_U##_NAME, \ - TT32_UQ##_NAME, \ - TT32_UH##_NAME - -// -// Instruction types for 32-bit Thumb DSP instructions like SMLA -// -#define TT32_SET_SMLA_XY(_NAME) \ - TT32_##_NAME##BB, \ - TT32_##_NAME##BT, \ - TT32_##_NAME##TB, \ - TT32_##_NAME##TT - -// -// Instruction types for 32-bit Thumb DSP instructions like SMLAW -// -#define TT32_SET_SMLAW_Y(_NAME) \ - TT32_##_NAME##B, \ - TT32_##_NAME##T - -// -// Instruction types for 32-bit Thumb instructions with optional argument exchange -// -#define TT32_SET_MEDIA_X(_NAME) \ - TT32_##_NAME, \ - TT32_##_NAME##X - -// -// Instruction types for 32-bit Thumb instructions with optional result rounding -// -#define TT32_SET_MEDIA_R(_NAME) \ - TT32_##_NAME, \ - TT32_##_NAME##R - -// -// Instruction types for 32-bit Thumb instructions like LDC -// -#define TT32_SET_LDC(_NAME) \ - TT32_##_NAME##_IMM, \ - TT32_##_NAME##_UNINDEXED - -// -// Instruction types for VFP instructions with D and S variants -// -#define TT32_VFP_DS(_NAME) \ - TT32_##_NAME##_D, \ - TT32_##_NAME##_S - -// -// Instruction type enumeration -// -typedef enum armThumbTypeE { - - //////////////////////////////////////////////////////////////////////////// - // 16-bit instructions - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - TT16_ADC, - TT16_ADD1, - TT16_ADD2, - TT16_ADD3, - TT16_ADD4LL, - TT16_ADD4LH, - TT16_ADD4H, - TT16_ADD5, - TT16_ADD6, - TT16_ADD7, - TT16_AND, - TT16_ASR1, - TT16_ASR2, - TT16_BIC, - TT16_EOR, - TT16_LSL1, - TT16_LSL2, - TT16_LSR1, - TT16_LSR2, - TT16_MOV1, - TT16_MOV2, - TT16_MOV3LL, - TT16_MOV3LH, - TT16_MOV3H, - TT16_MUL, - TT16_MVN, - TT16_NEG, - TT16_ORR, - TT16_ROR, - TT16_SBC, - TT16_SUB1, - TT16_SUB2, - TT16_SUB3, - TT16_SUB4, - - // compare instructions - TT16_CMN, - TT16_CMP1, - TT16_CMP2, - TT16_CMP3LH, - TT16_CMP3H, - TT16_TST, - - // branch instructions - TT16_B1, - TT16_B2, - TT16_BLX2, - TT16_BX, - TT16_SWI, - TT16_BU, - - // miscellaneous instructions - TT16_CPS, - TT16_CBNZ, - TT16_CBZ, - TT16_SXTH, - TT16_SXTB, - TT16_UXTH, - TT16_UXTB, - TT16_REV, - TT16_REV16, - TT16_REVSH, - TT16_BKPT, - - // load and store instructions - TT16_LDR1, - TT16_LDR2, - TT16_LDR3, - TT16_LDR4, - TT16_LDRB1, - TT16_LDRB2, - TT16_LDRH1, - TT16_LDRH2, - TT16_LDRSB, - TT16_LDRSH, - TT16_STR1, - TT16_STR2, - TT16_STR3, - TT16_STRB1, - TT16_STRB2, - TT16_STRH1, - TT16_STRH2, - - // load and store multiple instructions - TT16_LDMIA, - TT16_POP, - TT16_PUSH, - TT16_STMIA, - - // if-then and hints - TT16_IT, - TT16_NOP, - TT16_YIELD, - TT16_WFE, - TT16_WFI, - TT16_SEV, - - //////////////////////////////////////////////////////////////////////////// - // 32-bit instructions - //////////////////////////////////////////////////////////////////////////// - - // data processing - TT32_SET_ADD (AND), - TT32_SET_ADD (TST), - TT32_SET_ADD (BIC), - TT32_SET_ADD (ORR), - TT32_SET_ADD (MOV), - TT32_SET_ADD (ORN), - TT32_SET_ADD (MVN), - TT32_SET_ADD (EOR), - TT32_SET_ADD (TEQ), - TT32_SET_ADD (ADD), - TT32_SET_ADD (CMN), - TT32_SET_ADD (ADC), - TT32_SET_ADD (SBC), - TT32_SET_ADD (SUB), - TT32_SET_ADD (CMP), - TT32_SET_ADD (RSB), - - // pack halfword - TT32_PKHBT, - TT32_PKHTB, - - // data processing (plain binary immediate) - TT32_ADD_PI, - TT32_ADD_ADR_PI, - TT32_SUB_PI, - TT32_SUB_ADR_PI, - TT32_MOV_PI, - TT32_MOVT_PI, - TT32_SSAT, - TT32_SSAT16, - TT32_SBFX, - TT32_BFI, - TT32_BFC, - TT32_USAT, - TT32_USAT16, - TT32_UBFX, - - // data processing (register) - TT32_LSL, - TT32_LSR, - TT32_ASR, - TT32_ROR, - TT32_SXTAH, - TT32_SXTH, - TT32_UXTAH, - TT32_UXTH, - TT32_SXTAB16, - TT32_SXTB16, - TT32_UXTAB16, - TT32_UXTB16, - TT32_SXTAB, - TT32_SXTB, - TT32_UXTAB, - TT32_UXTB, - - // parallel add/subtract instructions - TT32_SET_PAS (ADD16), - TT32_SET_PAS (ASX ), - TT32_SET_PAS (SAX ), - TT32_SET_PAS (SUB16), - TT32_SET_PAS (ADD8 ), - TT32_SET_PAS (SUB8 ), - - // miscellaneous operation instructions - TT32_QADD, - TT32_QDADD, - TT32_QSUB, - TT32_QDSUB, - TT32_REV, - TT32_REV16, - TT32_RBIT, - TT32_REVSH, - TT32_SEL, - TT32_CLZ, - - // multiply, divide, multiply accumulate and absolute difference instructions - TT32_MLA, - TT32_MUL, - TT32_MLS, - TT32_SDIV, - TT32_UDIV, - TT32_SET_SMLA_XY (SMLA), - TT32_SET_SMLA_XY (SMUL), - TT32_SET_MEDIA_X (SMLAD), - TT32_SET_MEDIA_X (SMUAD), - TT32_SET_SMLAW_Y (SMLAW), - TT32_SET_SMLAW_Y (SMULW), - TT32_SET_MEDIA_X (SMLSD), - TT32_SET_MEDIA_X (SMUSD), - TT32_SET_MEDIA_R (SMMLA), - TT32_SET_MEDIA_R (SMMUL), - TT32_SET_MEDIA_R (SMMLS), - TT32_USAD8, - TT32_USADA8, - TT32_SMLAL, - TT32_SMULL, - TT32_UMAAL, - TT32_UMLAL, - TT32_UMULL, - TT32_SET_SMLA_XY (SMLAL), - TT32_SET_MEDIA_X (SMLALD), - TT32_SET_MEDIA_X (SMLSLD), - - // branch and miscellaneous control instructions - TT32_B1, - TT32_B2, - TT32_BL, - TT32_MSR, - TT32_NOP, - TT32_YIELD, - TT32_WFE, - TT32_WFI, - TT32_SEV, - TT32_DBG, - TT32_MRS, - TT32_UNDEF, - TT32_CLREX, - TT32_DSB, - TT32_DMB, - TT32_ISB, - - // load and store multiple instructions - TT32_STMDB, - TT32_STMIA, - TT32_LDMDB, - TT32_LDMIA, - TT32_POPM, - TT32_PUSHM, - - // dual and exclusive instructions - TT32_LDRD_IMM, - TT32_STRD_IMM, - TT32_LDREX, - TT32_LDREXB, - TT32_LDREXH, - TT32_STREX, - TT32_STREXB, - TT32_STREXH, - TT32_TBB, - TT32_TBH, - - // load and store instructions - TT32_SET_LDR (LDR ), - TT32_SET_LDR (LDRH ), - TT32_SET_LDR (LDRB ), - TT32_SET_LDR (LDRSH), - TT32_SET_LDR (LDRSB), - TT32_SET_LDR (STR ), - TT32_SET_LDR (STRH ), - TT32_SET_LDR (STRB ), - TT32_SET_PLD (PLD ), - TT32_SET_PLD (PLI ), - TT32_UHINTH, - TT32_UHINTB, - - // coprocessor instructions - TT32_CDP, - TT32_CDP2, - TT32_SET_LDC (LDC ), - TT32_SET_LDC (LDC2), - TT32_MCR, - TT32_MCR2, - TT32_MRC, - TT32_MRC2, - TT32_SET_LDC (STC ), - TT32_SET_LDC (STC2), - TT32_MCRR, - TT32_MCRR2, - TT32_MRRC, - TT32_MRRC2, - - // VFP data processing instructions - TT32_VMLA_VFP, - TT32_VMLS_VFP, - TT32_VNMLS_VFP, - TT32_VNMLA_VFP, - TT32_VMUL_VFP, - TT32_VNMUL_VFP, - TT32_VADD_VFP, - TT32_VSUB_VFP, - TT32_VDIV_VFP, - TT32_VFNMA_VFP, - TT32_VFNMS_VFP, - TT32_VFMA_VFP, - TT32_VFMS_VFP, - TT32_VMOVI_VFP, - TT32_VMOVR_VFP, - TT32_VABS_VFP, - TT32_VNEG_VFP, - TT32_VSQRT_VFP, - TT32_VCVTBFH_VFP, - TT32_VCVTTFH_VFP, - TT32_VCVTBHF_VFP, - TT32_VCVTTHF_VFP, - TT32_VCMP_VFP, - TT32_VCMPE_VFP, - TT32_VCMP0_VFP, - TT32_VCMPE0_VFP, - TT32_VCVTFU_VFP, - TT32_VCVTFS_VFP, - TT32_VCVTFXUH_VFP, - TT32_VCVTFXUW_VFP, - TT32_VCVTFXSH_VFP, - TT32_VCVTFXSW_VFP, - TT32_VCVTUF_VFP, - TT32_VCVTRUF_VFP, - TT32_VCVTSF_VFP, - TT32_VCVTRSF_VFP, - TT32_VCVTXFSH_VFP, - TT32_VCVTXFSW_VFP, - TT32_VCVTXFUH_VFP, - TT32_VCVTXFUW_VFP, - - // Extension register load/store instructions - TT32_VFP_DS (VSTMIA), - TT32_VFP_DS (VSTMIAW), - TT32_VFP_DS (VSTR), - TT32_VFP_DS (VSTMDBW), - TT32_VFP_DS (VPUSH), - TT32_VFP_DS (VLDMIA), - TT32_VFP_DS (VLDMIAW), - TT32_VFP_DS (VPOP), - TT32_VFP_DS (VLDR), - TT32_VFP_DS (VLDMDBW), - - // 8, 16 and 32-bit transfer instructions between ARM core regs and extension regs - TT32_VMRS, - TT32_VMSR, - TT32_VMOVRS, - TT32_VMOVSR, - TT32_VMOVZR, - TT32_VMOVRZ, - - // 64-bit transfer instructions between ARM core regs and extension regs - TT32_VMOVRRD, - TT32_VMOVDRR, - TT32_VMOVRRSS, - TT32_VMOVSSRR, - - // KEEP LAST - TT_LAST - -} armThumbType; - - -//////////////////////////////////////////////////////////////////////////////// -// FIELD EXTRACTION MACROS -//////////////////////////////////////////////////////////////////////////////// - -#define OP_R0(_I) WIDTH(4,(_I)>> 0) -#define OP_R12(_I) WIDTH(4,(_I)>>12) -#define OP_R16(_I) WIDTH(4,(_I)>>16) -#define OP_F20(_I) WIDTH(1,(_I)>>20) -#define OP_COND_8(_I) WIDTH(4,(_I)>> 8) -#define OP_COND_22(_I) WIDTH(4,(_I)>>22) -#define OP_COND_28(_I) WIDTH(4,(_I)>>28) -#define OP_IT(_I) WIDTH(8,(_I)>> 0) -#define OP_R3_0(_I) WIDTH(3,(_I)>> 0) -#define OP_R3_3(_I) WIDTH(3,(_I)>> 3) -#define OP_R3_6(_I) WIDTH(3,(_I)>> 6) -#define OP_R3_8(_I) WIDTH(3,(_I)>> 8) -#define OP_R4_0(_I) WIDTH(4,(_I)>> 0) -#define OP_R4_8(_I) WIDTH(4,(_I)>> 8) -#define OP_R4_12(_I) WIDTH(4,(_I)>>12) -#define OP_R4_16(_I) WIDTH(4,(_I)>>16) -#define OP_U_1_5(_I) WIDTH(1,(_I)>> 5) -#define OP_U_1_7(_I) WIDTH(1,(_I)>> 7) -#define OP_U_1_19(_I) WIDTH(1,(_I)>>19) -#define OP_U_1_21(_I) WIDTH(1,(_I)>>21) -#define OP_U_2_4(_I) WIDTH(2,(_I)>> 4) -#define OP_U_2_10(_I) WIDTH(2,(_I)>>10) -#define OP_U_2_20(_I) WIDTH(2,(_I)>>20) -#define OP_U_2_21(_I) WIDTH(2,(_I)>>21) -#define OP_U_3_0(_I) WIDTH(3,(_I)>> 0) -#define OP_U_3_6(_I) WIDTH(3,(_I)>> 6) -#define OP_U_4_0(_I) WIDTH(4,(_I)>> 0) -#define OP_U_4_4(_I) WIDTH(4,(_I)>> 4) -#define OP_U_5_0(_I) WIDTH(5,(_I)>> 0) -#define OP_U_5_0_5(_I) (((WIDTH(4,(_I)>>0))<<1)|WIDTH(1,(_I)>>5)) -#define OP_U_5_6(_I) WIDTH(5,(_I)>> 6) -#define OP_U_7_0(_I) WIDTH(7,(_I)>> 0) -#define OP_U_7_1(_I) WIDTH(7,(_I)>> 1) -#define OP_U_8_0(_I) WIDTH(8,(_I)>> 0) -#define OP_U_8_16_0(_I) (((WIDTH(4,(_I)>>16))<<4) | WIDTH(4,(_I)>>0)) -#define OP_U_9(_I) WIDTH(1,(_I)>> 9) -#define OP_U_12_0(_I) WIDTH(12,(_I)>>0) -#define OP_U_23(_I) WIDTH(1,(_I)>>23) -#define OP_R4_0_H7(_I) (((WIDTH(1,(_I)>>7))<<3)|OP_R3_0(_I)) -#define OP_R4_3_H6(_I) (((WIDTH(1,(_I)>>6))<<3)|OP_R3_3(_I)) -#define OP_TS8(_I) (((Int32)((_I)<<24))>>23) -#define OP_TS11(_I) (((Int32)((_I)<<21))>>20) -#define OP_TU9_7_3(_I) ((WIDTH(1,(_I)>>9)<<6) | (WIDTH(5,(_I)>>3)<<1)) -#define OP_RL_16(_I) WIDTH(8,(_I)>>0) -#define OP_RL_16_LR(_I) (OP_RL_16(_I) | (((_I)&0x100) ? (1<>0) -#define OP_RL_32_SP(_I) (OP_RL_32(_I) & ~(1<> 4) -#define OP_AIF_0(_I) WIDTH(3,(_I)>> 0) -#define OP_MA(_I) WIDTH(1,(_I)>> 8) -#define OP_PI_10(_I) WIDTH(1,(_I)>>10) -#define OP_PI_24(_I) WIDTH(1,(_I)>>24) -#define OP_WB_8(_I) WIDTH(1,(_I)>> 8) -#define OP_WB_21(_I) WIDTH(1,(_I)>>21) -#define OP_CPNUM(_I) WIDTH(4,(_I)>> 8) -#define OP_CPOP1_4_4(_I) WIDTH(4,(_I)>> 4) -#define OP_CPOP1_4_20(_I) WIDTH(4,(_I)>>20) -#define OP_CPOP1_3_21(_I) WIDTH(3,(_I)>>21) -#define OP_CPOP2(_I) WIDTH(3,(_I)>> 5) -#define OP_LL(_I) WIDTH(1,(_I)>>22) -#define OP_V0_5(_I) ((OP_R0(_I) <<1) | WIDTH(1,(_I)>> 5)) -#define OP_V16_7(_I) ((OP_R16(_I)<<1) | WIDTH(1,(_I)>> 7)) -#define OP_V12_22(_I) ((OP_R12(_I)<<1) | WIDTH(1,(_I)>>22)) -#define OP_V5_0(_I) ((WIDTH(1,(_I)>>5) <<4) | OP_R0(_I)) -#define OP_V22_12(_I) ((WIDTH(1,(_I)>>22)<<4) | OP_R12(_I)) -#define OP_V7_16(_I) ((WIDTH(1,(_I)>>7) <<4) | OP_R16(_I)) -#define OP_U(_I) WIDTH(1,(_I)>>23) -#define OP_PI(_I) WIDTH(1,(_I)>>24) - - -//////////////////////////////////////////////////////////////////////////////// -// INSTRUCTION ATTRIBUTE TABLE -//////////////////////////////////////////////////////////////////////////////// - -// -// This defines whether the instruction sets flags -// -typedef enum setFlagsE { - SF_0, // don't set flags - SF_V, // set flags, show in disassembly using "s" suffix - SF_I, // set flags, not shown in instruction disassembly - SF_20_V, // set flags if field 20 set, show in disassembly - SF_IT, // only when not in if-then block -} setFlags; - -// -// This defines whether the instruction sets flags -// -typedef enum condSpecE { - CO_NA, // no condition - CO_8, // condition at 11:8 - CO_22, // condition at 25:22 - CO_28, // condition at 31:28 -} condSpec; - -// -// Define the location of register in an instruction -// -typedef enum rSpecE { - R_NA, // no register - R3_0, // 3-bit register specification at 2:0 - R3_3, // 3-bit register specification at 5:3 - R3_6, // 3-bit register specification at 8:6 - R3_8, // 3-bit register specification at 10:8 - R4_0, // 4-bit register specification at 3:0 - R4_8, // 4-bit register specification at 11:8 - R4_12, // 4-bit register specification at 15:12 - R4_16, // 4-bit register specification at 19:16 - R4_0H7, // 4-bit register specification at 7,2:0 - R4_3H6, // 4-bit register specification at 6,5:3 - R_PC, // register PC - R_SP, // register SP - R_LR, // register LR - V_0_5, // register at 3:0,5 - V_12_22, // register at 15:12,22 - V_16_7, // register at 19:16,7 - V_5_0, // register at 5,3:0 - V_22_12, // register at 22,15:12 - V_7_16, // register at 7,19:16 - V3_0, // register is 3bits wide at 2:0 -} rSpec; - -// -// Define the location of a constant in an instruction -// -typedef enum constSpecE { - CS_NA, // instruction has no constant - CS_U_2_4, // 2-bit unsigned constant at 5:4 - CS_U_2_4x8, // 2-bit unsigned constant at 5:4*8 - CS_U_2_10, // 2-bit unsigned constant at 11:10 - CS_U_3_6, // 3-bit unsigned constant at 8:6 - CS_U_4_4, // 4-bit unsigned constant at 8:5 - CS_U_4_0, // 4-bit unsigned constant at 4:0 - CS_U_5_6, // 5-bit unsigned constant at 10:6 - CS_U_5_6_SZ, // 5-bit unsigned constant at 10:6, scaled by size - CS_U_5_0_5M16, // 5-bit unsigned constant at 3:0, 5. Subtract from 16 to get value - CS_U_5_0_5M32, // 5-bit unsigned constant at 3:0, 5. Subtract from 32 to get value - CS_U_7_0x4, // 7-bit unsigned constant at 6:0*4 - CS_U_8_0, // 8-bit unsigned constant at 7:0 - CS_U_8_0_U, // 8-bit unsigned constant at 7:0, negated if U=0 - CS_U_8_0_SZ, // 8-bit unsigned constant at 7:0, scaled by size - CS_U_8_0x4_U, // 8-bit unsigned constant at 7:0*4, negated if U=0 - CS_U_8_0x4, // 8-bit unsigned constant at 7:0*4 - CS_U_12_0, // 12-bit unsigned constant at 11:0 - CS_U_12_0_U, // 12-bit unsigned constant at 11:0, negated if U=0 - CS_PI5, // 5-bit plain immediate - CS_PI12, // 12-bit plain immediate - CS_PI16, // 16-bit plain immediate - CS_MI // modified immediate -} constSpec; - -// -// This defines target address field in the instruction -// -typedef enum targetSpecE { - TC_NA, // no target - TC_S8, // target PC + s8 field (2-byte aligned) - TC_S11, // target PC + s11 field (2-byte aligned) - TC_S20_T2, // target PC + s20 field (2-byte aligned) - TC_S24_T2, // target PC + s24 field (2-byte aligned) - TC_U9_7_3 // target PC + unsigned constant at 9,7:3*2 -} targetSpec; - -// -// This defines shift in the instruction -// -typedef enum shiftSpecE { - SS_NA, // no shift operation - SS_ASR, // ASR - SS_LSL, // LSL - SS_LSR, // LSR - SS_ROR, // ROR - SS_RRX, // RRX - SS2_4, // shift spec at offset 5:4 - SS2_20, // shift spec at offset 21:20 - SS2_21, // shift spec at offset 22:21 -} shiftSpec; - -// -// This defines whether the instruction specifies post-indexed addressing -// -typedef enum postIndexSpecE { - PI_0, // not post-indexed - PI_1, // post-indexed - PI_10, // post-indexed at position 10 - PI_24, // post-indexed at position 24 -} postIndexSpec; - -// -// This defines whether the instruction specifies writeback -// -typedef enum writebackSpecE { - WB_0, // no writeback - WB_1, // writeback - WB_1_NB, // writeback unless base in register list - WB_8, // writeback at position 8 - WB_21 // writeback at position 21 -} writebackSpec; - -// -// This defines coprocessor opcode field in the instruction -// -typedef enum cpOp1SpecE { - COP_NA, // no opcode1 field - COP_4_4, // 4-bit constant at offset 7:4 - COP_4_20, // 4-bit constant at offset 23:20 - COP_3_21 // 3-bit constant at offset 23:21 -} cpOp1Spec; - -// -// This defines register list field in the instruction -// -typedef enum rListSpecE { - RL_NA, // no register list - RL_16, // register list in 16-bit Thumb opcode - RL_16_LR, // register list in 16-bit Thumb opcode, possibly including LR - RL_16_PC, // register list in 16-bit Thumb opcode, possibly including PC - RL_32_SP, // register list in 32-bit Thumb opcode, excluding SP - RL_32_PCSP, // register list in 32-bit Thumb opcode, excluding PC & SP -} rListSpec; - -// -// This defines increment/decrement specification in the instruction -// -typedef enum incDecSpecE { - ID_NA, // no increment/decrement specification - ID_U_P, // increment/decrement defined by U and P bits - ID_DB, // increment/decrement specification is Decrement Before - ID_IA, // increment/decrement specification is Increment After - ID_U_P_IAI, // increment/decrement defined by U and P bits, IA is implicit in disassembly (UAL only) - ID_U_P_IMP, // increment/decrement defined by U and P bits, IA is always implicit in disassembly - ID_DB_I, // increment/decrement specification is Decrement Before, Implicit in disassembly - ID_IA_I, // increment/decrement specification is Increment After, Implicit in disassembly -} incDecSpec; - -// -// This defines interrupt enable/disable fields in the instruction -// -typedef enum imodSpecE { - IS_NA, // no imod spec - IS_4 // imod spec at bit 4 -} imodSpec; - -// -// This defines interrupt disable bits in the instruction -// -typedef enum aifSpecE { - AIF_NA, // no aif spec - AIF_0 // aif field at 2:0 -} aifSpec; - -// -// This defines width field in the instruction -// -typedef enum widthSpecE { - WS_NA, // no width specification - WS_WIDTH4, // width in field 3:0 - WS_WIDTH4M1, // width in field 3:0+1 - WS_WIDTH5, // width in field 4:0 - WS_WIDTH5M1, // width in field 4:0+1 - WS_MSB // width in field 4:0 - {14:12,7:6} + 1; -} widthSpec; - -// -// This defines u field in the instruction -// -typedef enum uSpecE { - US_1, // u=1 - US_9, // u in field at position 9 - US_23, // u in field at position 23 -} uSpec; - -// -// This defines mask field in MSR instruction -// -typedef enum maskSpecE { - MSRMASK_NA, // no MSR mask spec - MSRMASK_10 // mask field in bits 11:10 -} maskSpec; - -// -// Define a SIMD/VFP modified immediate constant type -// -typedef enum sdfpMISpecE { - SDFP_MI_NA, // instruction has no SIMD/VFP modified immediate constant - SDFP_MI_VFP_S, // single precision VFP modified immediate value -} sdfpMISpec; - -// -// This defines the SIMD scalar index field in the instruction -// -typedef enum indexSpecE { - IDX_NA, // no index specification - IDX_21, // index is 1 bit wide, in bit 21 - IDX_5, // index is 1 bit wide, in bit 5 - IDX_7, // index is 1 bit wide, in bit 7 - IDX_19, // index is 1 bit wide, in bit 19 -} indexSpec; - -// -// This defines the number of regs in a VFP register list -// -typedef enum nregSpecE { - NREG_NA, // no alignment specification - NREG_7_1, // Nregs is 7 bits wide in bits 7:1 - NREG_8_0, // Nregs is 8 bits wide in bits 7:0 -} nregSpec; - -// -// Structure defining characteristics of each opcode type -// -typedef struct opAttrsS { - const char *opcode; // opcode name - const char *format; // format string - armInstructionType type; // equivalent ARM instruction - armArchitecture support:16; // variants on which instruction supported - armISARSupport isar : 8; // ISAR instruction support - setFlags f : 4; // does this opcode set flags? - condSpec cond : 4; // condition field specification - rSpec r1 : 8; // does instruction have r1? - rSpec r2 : 8; // does instruction have r2? - rSpec r3 : 8; // does instruction have r3? - rSpec r4 : 8; // does instruction have r4? - constSpec cs : 8; // location of constant - targetSpec ts : 4; // target specification - shiftSpec ss : 4; // shifter specification - Uns8 sz : 4; // load/store size - Uns8 xs : 4; // sign extend? - Uns8 tl : 4; // translate? - postIndexSpec pi : 4; // instruction specifies post-indexed address? - writebackSpec wb : 4; // instruction specifies writeback? - Uns8 ll : 4; // instruction specifies long load? - Uns8 cpNum : 4; // does instruction have coprocessor number? - cpOp1Spec cpOp1 : 4; // does instruction have coprocessor op 1? - Uns8 cpOp2 : 4; // does instruction have coprocessor op 2? - rListSpec rList : 4; // does instruction have register list? - incDecSpec incDec : 4; // does instruction have increment/decrement? - armUnalignedAction ua45 : 4; // action if unaligned (Control.U=0) - armUnalignedAction ua67 : 4; // action if unaligned (Control.U=1) - Bool ea : 1; // exclusive access? - imodSpec imod : 4; // imod field specification - Bool m : 1; // M field present? - aifSpec aif : 4; // A/I/F fields specification - Bool it : 1; // IT specification present? - widthSpec w : 4; // width specification - uSpec u : 4; // U bit specification - maskSpec mask : 4; // mask specification (MSR instruction) - indexSpec index : 4; // VFP scalar index specification? - nregSpec nregs : 4; // number of regs in VFP register list specification? - sdfpMISpec sdfpMI : 4; // SIMD/floating point modified immediate constant? - armSDFPType dt1 : 8; // SIMD/VFP first data type? - armSDFPType dt2 : 8; // SIMD/VFP second data type? -} opAttrs; - -typedef const struct opAttrsS *opAttrsCP; - -// -// This specifies attributes for each opcode -// -const static opAttrs attrsArray[TT_LAST+1] = { - - //////////////////////////////////////////////////////////////////////////// - // 16-bit instructions - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - ATTR_SET_16_ADC (ADC, ADC_RT, ARM_VT, ARM_ISAR_NA, "adc" ), - ATTR_SET_16_ADD1 (ADD1, ADD_IMM, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD2 (ADD2, ADD_IT, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD3 (ADD3, ADD_RM, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD4 (ADD4LL, ADD4, ARM_VT2, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD4 (ADD4LH, ADD4, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD4 (ADD4H, ADD4, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD5 (ADD5, ADD_ADR, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD6 (ADD6, ADD6, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ADD7 (ADD7, ADD7, ARM_VT, ARM_ISAR_NA, "add" ), - ATTR_SET_16_ASR1 (ASR1, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "asr", SS_ASR), - ATTR_SET_16_ASR2 (ASR2, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "asr", SS_ASR), - ATTR_SET_16_ADC (AND, AND_RT, ARM_VT, ARM_ISAR_NA, "and" ), - ATTR_SET_16_ADC (BIC, BIC_RT, ARM_VT, ARM_ISAR_NA, "bic" ), - ATTR_SET_16_ADC (EOR, EOR_RT, ARM_VT, ARM_ISAR_NA, "eor" ), - ATTR_SET_16_ASR1 (LSL1, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "lsl", SS_LSL), - ATTR_SET_16_ASR2 (LSL2, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "lsl", SS_LSL), - ATTR_SET_16_ASR1 (LSR1, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "lsr", SS_LSR), - ATTR_SET_16_ASR2 (LSR2, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "lsr", SS_LSR), - ATTR_SET_16_ADD2 (MOV1, MOV_IMM, ARM_VT, ARM_ISAR_NA, "mov" ), - ATTR_SET_16_MOV2 (MOV2, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "mov" ), - ATTR_SET_16_ADD4 (MOV3LL, MOV3, 6|ARM_VT, ARM_ISAR_MOVLL, "mov" ), - ATTR_SET_16_ADD4 (MOV3LH, MOV3, ARM_VT, ARM_ISAR_NA, "mov" ), - ATTR_SET_16_ADD4 (MOV3H, MOV3, ARM_VT, ARM_ISAR_NA, "mov" ), - ATTR_SET_16_ADC (MUL, MUL_RT, ARM_VT, ARM_ISAR_NA, "mul" ), - ATTR_SET_16_ADC (MVN, MVN_RM, ARM_VT, ARM_ISAR_NA, "mvn" ), - ATTR_SET_16_ADC (NEG, NEG_RM, ARM_VT, ARM_ISAR_NA, "neg" ), - ATTR_SET_16_ADC (ORR, ORR_RT, ARM_VT, ARM_ISAR_NA, "orr" ), - ATTR_SET_16_ASR2 (ROR, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "ror", SS_ROR), - ATTR_SET_16_ADC (SBC, SBC_RT, ARM_VT, ARM_ISAR_NA, "sbc" ), - ATTR_SET_16_ADD1 (SUB1, SUB_IMM, ARM_VT, ARM_ISAR_NA, "sub" ), - ATTR_SET_16_ADD2 (SUB2, SUB_IT, ARM_VT, ARM_ISAR_NA, "sub" ), - ATTR_SET_16_ADD3 (SUB3, SUB_RM, ARM_VT, ARM_ISAR_NA, "sub" ), - ATTR_SET_16_ADD7 (SUB4, SUB4, ARM_VT, ARM_ISAR_NA, "sub" ), - - // compare instructions - ATTR_SET_16_CMP2 (CMN, CMN_RM, ARM_VT, ARM_ISAR_NA, "cmn"), - ATTR_SET_16_CMP1 (CMP1, CMP_IMM, ARM_VT, ARM_ISAR_NA, "cmp"), - ATTR_SET_16_CMP2 (CMP2, CMP_RM, ARM_VT, ARM_ISAR_NA, "cmp"), - ATTR_SET_16_CMP3 (CMP3LH, CMP_RM, ARM_VT, ARM_ISAR_NA, "cmp"), - ATTR_SET_16_CMP3 (CMP3H, CMP_RM, ARM_VT, ARM_ISAR_NA, "cmp"), - ATTR_SET_16_CMP2 (TST, TST_RM, ARM_VT, ARM_ISAR_NA, "tst"), - - // branch instructions - ATTR_SET_16_B1 (B1, B, ARM_VT, ARM_ISAR_NA, "b" ), - ATTR_SET_16_B2 (B2, B, ARM_VT, ARM_ISAR_NA, "b" ), - ATTR_SET_16_BLX2 (BLX2, 5|ARM_VT, ARM_ISAR_BLX, "blx"), - ATTR_SET_16_BLX2 (BX, ARM_VT, ARM_ISAR_BX, "bx" ), - ATTR_SET_16_BKPT (SWI, ARM_VT, ARM_ISAR_SVC, "svc"), - ATTR_SET_16_UNDECODED (BU ), - - // miscellaneous instructions - ATTR_SET_16_CPS (CPS, 6|ARM_VT, ARM_ISAR_MRS_M, "cps" ), - ATTR_SET_16_CBNZ (CBNZ, ARM_VT2, ARM_ISAR_CBZ, "cbnz" ), - ATTR_SET_16_CBNZ (CBZ, ARM_VT2, ARM_ISAR_CBZ, "cbz" ), - ATTR_SET_16_SXTH (SXTH, 6|ARM_VT, ARM_ISAR_SXTB, "sxth" ), - ATTR_SET_16_SXTH (SXTB, 6|ARM_VT, ARM_ISAR_SXTB, "sxtb" ), - ATTR_SET_16_SXTH (UXTH, 6|ARM_VT, ARM_ISAR_SXTB, "uxth" ), - ATTR_SET_16_SXTH (UXTB, 6|ARM_VT, ARM_ISAR_SXTB, "uxtb" ), - ATTR_SET_16_SXTH (REV, 6|ARM_VT, ARM_ISAR_REV, "rev" ), - ATTR_SET_16_SXTH (REV16, 6|ARM_VT, ARM_ISAR_REV, "rev16"), - ATTR_SET_16_SXTH (REVSH, 6|ARM_VT, ARM_ISAR_REV, "revsh"), - ATTR_SET_16_BKPT (BKPT, 5|ARM_VT, ARM_ISAR_BKPT, "bkpt" ), - - // load and store instructions - ATTR_SET_16_LDR1 (LDR1, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (LDR2, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR3 (LDR3, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR4 (LDR4, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR1 (LDRB1, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (LDRB2, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR1 (LDRH1, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (LDRH2, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (LDRSB, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 1, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (LDRSH, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 2, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR1 (STR1, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (STR2, STR_RM, ARM_VT, ARM_ISAR_NA, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR4 (STR3, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR1 (STRB1, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (STRB2, STR_RM, ARM_VT, ARM_ISAR_NA, "str", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR1 (STRH1, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_16_LDR2 (STRH2, STR_RM, ARM_VT, ARM_ISAR_NA, "str", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - - // load and store multiple instructions - ATTR_SET_16_LDMIA (LDMIA, LDM1, ARM_VT, ARM_ISAR_NA, "ldm", RL_16, ID_IA, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_16_POP (POP, LDM1, ARM_VT, ARM_ISAR_NA, "pop", RL_16_PC, ID_IA_I, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_16_POP (PUSH, STM1, ARM_VT, ARM_ISAR_NA, "push", RL_16_LR, ID_DB_I, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_16_STMIA (STMIA, STM1, ARM_VT, ARM_ISAR_NA, "stm", RL_16, ID_IA, ARM_UA_ALIGN, ARM_UA_DABORT), - - // if-then and hints - ATTR_SET_16_IT (IT, NOP, ARM_VT2, ARM_ISAR_IT, "it" ), - ATTR_SET_16_NOP (NOP, NOP, ARM_VT2, ARM_ISAR_NOP, "nop" ), - ATTR_SET_16_NOP (YIELD, YIELD, ARM_VT2, ARM_ISAR_NOP, "yield"), - ATTR_SET_16_NOP (WFE, WFE, ARM_VT2, ARM_ISAR_NOP, "wfe" ), - ATTR_SET_16_NOP (WFI, WFI, ARM_VT2, ARM_ISAR_NOP, "wfi" ), - ATTR_SET_16_NOP (SEV, SEV, ARM_VT2, ARM_ISAR_NOP, "sev" ), - - //////////////////////////////////////////////////////////////////////////// - // 32-bit instructions - //////////////////////////////////////////////////////////////////////////// - - // data processing - ATTR_SET_32_AND (AND, ARM_VT2, ARM_ISAR_NA, "and"), - ATTR_SET_32_TST (TST, ARM_VT2, ARM_ISAR_NA, "tst"), - ATTR_SET_32_AND (BIC, ARM_VT2, ARM_ISAR_NA, "bic"), - ATTR_SET_32_AND (ORR, ARM_VT2, ARM_ISAR_NA, "orr"), - ATTR_SET_32_MOV (MOV, ARM_VT2, ARM_ISAR_NA, "mov"), - ATTR_SET_32_AND (ORN, ARM_VT2, ARM_ISAR_NA, "orn"), - ATTR_SET_32_MOV (MVN, ARM_VT2, ARM_ISAR_NA, "mvn"), - ATTR_SET_32_AND (EOR, ARM_VT2, ARM_ISAR_NA, "eor"), - ATTR_SET_32_TST (TEQ, ARM_VT2, ARM_ISAR_NA, "teq"), - ATTR_SET_32_AND (ADD, ARM_VT2, ARM_ISAR_NA, "add"), - ATTR_SET_32_TST (CMN, ARM_VT2, ARM_ISAR_NA, "cmn"), - ATTR_SET_32_AND (ADC, ARM_VT2, ARM_ISAR_NA, "adc"), - ATTR_SET_32_AND (SBC, ARM_VT2, ARM_ISAR_NA, "sbc"), - ATTR_SET_32_AND (SUB, ARM_VT2, ARM_ISAR_NA, "sub"), - ATTR_SET_32_TST (CMP, ARM_VT2, ARM_ISAR_NA, "cmp"), - ATTR_SET_32_AND (RSB, ARM_VT2, ARM_ISAR_NA, "rsb"), - - // pack halfword - ATTR_SET_32_PKHBT (PKHBT, ARM_VT2, ARM_ISAR_PKHBT, "pkhbt"), - ATTR_SET_32_PKHBT (PKHTB, ARM_VT2, ARM_ISAR_PKHBT, "pkhtb"), - - // data processing (plain binary immediate) - ATTR_SET_32_ADD_PI (ADD_PI, ADD_IMM, ARM_VT2, ARM_ISAR_MOVT, "addw"), - ATTR_SET_32_ADD_PI (ADD_ADR_PI, ADD_ADR, ARM_VT2, ARM_ISAR_MOVT, "addw"), - ATTR_SET_32_ADD_PI (SUB_PI, SUB_IMM, ARM_VT2, ARM_ISAR_MOVT, "subw"), - ATTR_SET_32_ADD_PI (SUB_ADR_PI, SUB_ADR, ARM_VT2, ARM_ISAR_MOVT, "subw"), - ATTR_SET_32_MOV_PI (MOV_PI, MOVW, ARM_VT2, ARM_ISAR_MOVT, "movw"), - ATTR_SET_32_MOV_PI (MOVT_PI, MOVT, ARM_VT2, ARM_ISAR_MOVT, "movt"), - ATTR_SET_32_SSAT (SSAT, SSAT, ARM_VT2, ARM_ISAR_SSAT, "ssat"), - ATTR_SET_32_SSAT16 (SSAT16, SSAT16, ARM_VT2, ARM_ISAR_PKHBT, "ssat16"), - ATTR_SET_32_SBFX (SBFX, SBFX, ARM_VT2, ARM_ISAR_BFC, "sbfx"), - ATTR_SET_32_BFI (BFI, BFI, ARM_VT2, ARM_ISAR_BFC, "bfi" ), - ATTR_SET_32_BFC (BFC, BFC, ARM_VT2, ARM_ISAR_BFC, "bfc" ), - ATTR_SET_32_USAT (USAT, USAT, ARM_VT2, ARM_ISAR_SSAT, "usat"), - ATTR_SET_32_USAT16 (USAT16, USAT16, ARM_VT2, ARM_ISAR_PKHBT, "usat16"), - ATTR_SET_32_SBFX (UBFX, UBFX, ARM_VT2, ARM_ISAR_BFC, "ubfx"), - - // data processing (register) - ATTR_SET_32_LSL (LSL, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "lsl" ), - ATTR_SET_32_LSL (LSR, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "lsr" ), - ATTR_SET_32_LSL (ASR, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "asr" ), - ATTR_SET_32_LSL (ROR, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "ror" ), - ATTR_SET_32_SXTAH (SXTAH, ARM_VT2, ARM_ISAR_SXTAB, "sxtah" ), - ATTR_SET_32_SXTH (SXTH, ARM_VT2, ARM_ISAR_SXTB, "sxth" ), - ATTR_SET_32_SXTAH (UXTAH, ARM_VT2, ARM_ISAR_SXTAB, "uxtah" ), - ATTR_SET_32_SXTH (UXTH, ARM_VT2, ARM_ISAR_SXTB, "uxth" ), - ATTR_SET_32_SXTAH (SXTAB16, ARM_VT2, ARM_ISAR_SXTB16, "sxtab16"), - ATTR_SET_32_SXTH (SXTB16, ARM_VT2, ARM_ISAR_SXTB16, "sxtb16" ), - ATTR_SET_32_SXTAH (UXTAB16, ARM_VT2, ARM_ISAR_SXTB16, "uxtab16"), - ATTR_SET_32_SXTH (UXTB16, ARM_VT2, ARM_ISAR_SXTB16, "uxtb16" ), - ATTR_SET_32_SXTAH (SXTAB, ARM_VT2, ARM_ISAR_SXTAB, "sxtab" ), - ATTR_SET_32_SXTH (SXTB, ARM_VT2, ARM_ISAR_SXTB, "sxtb" ), - ATTR_SET_32_SXTAH (UXTAB, ARM_VT2, ARM_ISAR_SXTAB, "uxtab" ), - ATTR_SET_32_SXTH (UXTB, ARM_VT2, ARM_ISAR_SXTB, "uxtb" ), - - // parallel add/subtract instructions - ATTR_SET_32_PAS (ADD16, ARM_VT2, ARM_ISAR_PKHBT, "add16"), - ATTR_SET_32_PAS (ASX, ARM_VT2, ARM_ISAR_PKHBT, "asx" ), - ATTR_SET_32_PAS (SAX, ARM_VT2, ARM_ISAR_PKHBT, "sax" ), - ATTR_SET_32_PAS (SUB16, ARM_VT2, ARM_ISAR_PKHBT, "sub16"), - ATTR_SET_32_PAS (ADD8, ARM_VT2, ARM_ISAR_PKHBT, "add8" ), - ATTR_SET_32_PAS (SUB8, ARM_VT2, ARM_ISAR_PKHBT, "sub8" ), - - // miscellaneous operation instructions - ATTR_SET_32_QADD (QADD, ARM_VT2, ARM_ISAR_QADD, "qadd" ), - ATTR_SET_32_QADD (QDADD, ARM_VT2, ARM_ISAR_QADD, "qdadd"), - ATTR_SET_32_QADD (QSUB, ARM_VT2, ARM_ISAR_QADD, "qsub" ), - ATTR_SET_32_QADD (QDSUB, ARM_VT2, ARM_ISAR_QADD, "qdsub"), - ATTR_SET_32_CLZ (REV, ARM_VT2, ARM_ISAR_REV, "rev" ), - ATTR_SET_32_CLZ (REV16, ARM_VT2, ARM_ISAR_REV, "rev16"), - ATTR_SET_32_CLZ (RBIT, ARM_VT2, ARM_ISAR_RBIT, "rbit" ), - ATTR_SET_32_CLZ (REVSH, ARM_VT2, ARM_ISAR_REV, "revsh"), - ATTR_SET_32_SEL (SEL, ARM_VT2, ARM_ISAR_PKHBT, "sel" ), - ATTR_SET_32_CLZ (CLZ, ARM_VT2, ARM_ISAR_CLZ, "clz" ), - - // multiply, multiply accumulate and absolute difference instructions - ATTR_SET_32_MLA (MLA, ARM_VT2, ARM_ISAR_MLA, "mla" ), - ATTR_SET_32_MUL (MUL, ARM_VT2, ARM_ISAR_NA, "mul" ), - ATTR_SET_32_MLA (MLS, ARM_VT2, ARM_ISAR_MLS, "mls" ), - ATTR_SET_32_MUL (SDIV, 7, ARM_ISAR_DIV, "sdiv" ), - ATTR_SET_32_MUL (UDIV, 7, ARM_ISAR_DIV, "udiv" ), - ATTR_SET_32_SMLA_XY (SMLA, ARM_VT2, ARM_ISAR_SMLABB, "smla" ), - ATTR_SET_32_SMUL_XY (SMUL, ARM_VT2, ARM_ISAR_SMLABB, "smul" ), - ATTR_SET_32_SMLAD (SMLAD, ARM_VT2, ARM_ISAR_SMLAD, "smlad" ), - ATTR_SET_32_SMUAD (SMUAD, ARM_VT2, ARM_ISAR_SMLAD, "smuad" ), - ATTR_SET_32_SMLAW (SMLAW, ARM_VT2, ARM_ISAR_SMLABB, "smlaw" ), - ATTR_SET_32_SMULW (SMULW, ARM_VT2, ARM_ISAR_SMLABB, "smulw" ), - ATTR_SET_32_SMLAD (SMLSD, ARM_VT2, ARM_ISAR_SMLAD, "smlsd" ), - ATTR_SET_32_SMUAD (SMUSD, ARM_VT2, ARM_ISAR_SMLAD, "smusd" ), - ATTR_SET_32_SMMLA (SMMLA, ARM_VT2, ARM_ISAR_SMLAD, "smmla" ), - ATTR_SET_32_SMMUL (SMMUL, ARM_VT2, ARM_ISAR_SMLAD, "smmul" ), - ATTR_SET_32_SMMLA (SMMLS, ARM_VT2, ARM_ISAR_SMLAD, "smmls" ), - ATTR_SET_32_MUL (USAD8, ARM_VT2, ARM_ISAR_PKHBT, "usad8" ), - ATTR_SET_32_MLA (USADA8, ARM_VT2, ARM_ISAR_PKHBT, "usada8"), - ATTR_SET_32_SMLAL (SMLAL, ARM_VT2, ARM_ISAR_SMULL, "smlal" ), - ATTR_SET_32_SMLAL (SMULL, ARM_VT2, ARM_ISAR_SMULL, "smull" ), - ATTR_SET_32_SMLAL (UMAAL, ARM_VT2, ARM_ISAR_UMAAL, "umaal" ), - ATTR_SET_32_SMLAL (UMLAL, ARM_VT2, ARM_ISAR_UMULL, "umlal" ), - ATTR_SET_32_SMLAL (UMULL, ARM_VT2, ARM_ISAR_UMULL, "umull" ), - ATTR_SET_32_SMLAL_XY (SMLAL, ARM_VT2, ARM_ISAR_SMLABB, "smlal" ), - ATTR_SET_32_SMLALD (SMLALD, ARM_VT2, ARM_ISAR_SMLAD, "smlald"), - ATTR_SET_32_SMLALD (SMLSLD, ARM_VT2, ARM_ISAR_SMLAD, "smlsld"), - - // branch and miscellaneous control instructions - ATTR_SET_32_B1 (B1, B, ARM_VT2, ARM_ISAR_NA, "b" ), - ATTR_SET_32_BL (B2, B, ARM_VT2, ARM_ISAR_NA, "b" ), - ATTR_SET_32_BL (BL, BL, ARM_VT, ARM_ISAR_NA, "bl" ), - ATTR_SET_32_MSR (MSR, 7, ARM_ISAR_MRS_M, "msr" ), - ATTR_SET_32_NOP (NOP, ARM_VT2, ARM_ISAR_NOP, "nop" ), - ATTR_SET_32_NOP (YIELD, ARM_VT2, ARM_ISAR_NOP, "yield"), - ATTR_SET_32_NOP (WFE, ARM_VT2, ARM_ISAR_NOP, "wfe" ), - ATTR_SET_32_NOP (WFI, ARM_VT2, ARM_ISAR_NOP, "wfi" ), - ATTR_SET_32_NOP (SEV, ARM_VT2, ARM_ISAR_NOP, "sev" ), - ATTR_SET_32_DBG (DBG, ARM_VT2, ARM_ISAR_NOP, "dbg" ), - ATTR_SET_32_MRS (MRS, 7, ARM_ISAR_MRS_M, "mrs" ), - ATTR_SET_32_UND (UNDEF, ARM_VT2, ARM_ISAR_NA ), - ATTR_SET_32_NOP (CLREX, 7, ARM_ISAR_CLREX, "clrex"), - ATTR_SET_32_DSB (DSB, 7, ARM_ISAR_DMB, "dsb" ), - ATTR_SET_32_DSB (DMB, 7, ARM_ISAR_DMB, "dmb" ), - ATTR_SET_32_DSB (ISB, 7, ARM_ISAR_DMB, "isb" ), - - // load and store multiple instructions - ATTR_SET_32_LDM (STMDB, STM1, ARM_VT2, ARM_ISAR_NA, "stm", ID_DB, RL_32_PCSP, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_LDM (STMIA, STM1, ARM_VT2, ARM_ISAR_NA, "stm", ID_IA, RL_32_PCSP, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_LDM (LDMDB, LDM1, ARM_VT2, ARM_ISAR_NA, "ldm", ID_DB, RL_32_SP, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_LDM (LDMIA, LDM1, ARM_VT2, ARM_ISAR_NA, "ldm", ID_IA, RL_32_SP, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_POPM (POPM, LDM1, ARM_VT2, ARM_ISAR_NA, "pop", ID_IA_I, RL_32_SP, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_POPM (PUSHM, STM1, ARM_VT2, ARM_ISAR_NA, "push", ID_DB_I, RL_32_PCSP, ARM_UA_ALIGN, ARM_UA_DABORT), - - // dual and exclusive instructions - ATTR_SET_32_LDRD_IMM (LDRD_IMM, ARM_VT2, ARM_ISAR_LDRD, "ldr", 8, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_LDRD_IMM (STRD_IMM, ARM_VT2, ARM_ISAR_LDRD, "str", 8, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_LDREX (LDREX, ARM_VT2, ARM_ISAR_LDREX, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_LDREXB (LDREXB, 7, ARM_ISAR_CLREX, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_LDREXB (LDREXH, 7, ARM_ISAR_CLREX, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_STREX (STREX, ARM_VT2, ARM_ISAR_LDREX, "str", 4, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_STREXB (STREXB, 7, ARM_ISAR_CLREX, "str", 1, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_STREXB (STREXH, 7, ARM_ISAR_CLREX, "str", 2, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_TBB (TBB, TB, ARM_VT2, ARM_ISAR_TBB, "tb", 1, False, ARM_UA_ALIGN, ARM_UA_DABORT), - ATTR_SET_32_TBB (TBH, TB, ARM_VT2, ARM_ISAR_TBB, "tb", 2, False, ARM_UA_ALIGN, ARM_UA_DABORT), - - // load instructions - ATTR_SET_32_LDR (LDR, LDR, ARM_VT2, ARM_ISAR_LDRBT, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_LDR (LDRH, LDR, ARM_VT2, ARM_ISAR_LDRHT, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_LDR (LDRB, LDR, ARM_VT2, ARM_ISAR_LDRBT, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_LDR (LDRSH, LDR, ARM_VT2, ARM_ISAR_LDRHT, "ldr", 2, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_LDR (LDRSB, LDR, ARM_VT2, ARM_ISAR_LDRHT, "ldr", 1, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_LDR (STR, STR, ARM_VT2, ARM_ISAR_LDRBT, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_LDR (STRH, STR, ARM_VT2, ARM_ISAR_LDRHT, "str", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_LDR (STRB, STR, ARM_VT2, ARM_ISAR_LDRBT, "str", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_PLD (PLD, PLD, ARM_VT2, ARM_ISAR_PLD, "pld", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_PLD (PLI, PLI, ARM_VT2, ARM_ISAR_PLI, "pli", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED), - ATTR_SET_32_UHINTH (UHINTH, NOP, ARM_VT2, ARM_ISAR_NA, "nop" ), - ATTR_SET_32_UHINTH (UHINTB, NOP, ARM_VT2, ARM_ISAR_NA, "nop" ), - - // coprocessor instructions - ATTR_SET_32_CDP (CDP, ARM_VT2, ARM_ISAR_NA, "cdp" ), - ATTR_SET_32_CDP2 (CDP2, ARM_VT2, ARM_ISAR_NA, "cdp2" ), - ATTR_SET_32_LDC (LDC, ARM_VT2, ARM_ISAR_NA, "ldc" ), - ATTR_SET_32_LDC2 (LDC2, ARM_VT2, ARM_ISAR_NA, "ldc2" ), - ATTR_SET_32_MCR (MCR, ARM_VT2, ARM_ISAR_NA, "mcr" ), - ATTR_SET_32_MCR2 (MCR2, ARM_VT2, ARM_ISAR_NA, "mcr2" ), - ATTR_SET_32_MRC (MRC, ARM_VT2, ARM_ISAR_NA, "mrc" ), - ATTR_SET_32_MRC2 (MRC2, ARM_VT2, ARM_ISAR_NA, "mrc2" ), - ATTR_SET_32_LDC (STC, ARM_VT2, ARM_ISAR_NA, "stc" ), - ATTR_SET_32_LDC2 (STC2, ARM_VT2, ARM_ISAR_NA, "stc2" ), - ATTR_SET_32_MCRR (MCRR, ARM_VT2, ARM_ISAR_NA, "mcrr" ), - ATTR_SET_32_MCRR2 (MCRR2, ARM_VT2, ARM_ISAR_NA, "mcrr2"), - ATTR_SET_32_MCRR (MRRC, ARM_VT2, ARM_ISAR_NA, "mrrc" ), - ATTR_SET_32_MCRR2 (MRRC2, ARM_VT2, ARM_ISAR_NA, "mrrc2"), - - //////////////////////////////////////////////////////////////////////////// - // VFP Instructions (single precision only) - //////////////////////////////////////////////////////////////////////////// - - // VFP data processing instructions - ATTR_SET_32_VFP_RRR (VMLA_VFP, 7, ARM_ISAR_VFPV2, "vmla"), - ATTR_SET_32_VFP_RRR (VMLS_VFP, 7, ARM_ISAR_VFPV2, "vmls"), - ATTR_SET_32_VFP_RRR (VNMLS_VFP, 7, ARM_ISAR_VFPV2, "vnmls"), - ATTR_SET_32_VFP_RRR (VNMLA_VFP, 7, ARM_ISAR_VFPV2, "vnmla"), - ATTR_SET_32_VFP_RRR (VMUL_VFP, 7, ARM_ISAR_VFPV2, "vmul"), - ATTR_SET_32_VFP_RRR (VNMUL_VFP, 7, ARM_ISAR_VFPV2, "vnmul"), - ATTR_SET_32_VFP_RRR (VADD_VFP, 7, ARM_ISAR_VFPV2, "vadd"), - ATTR_SET_32_VFP_RRR (VSUB_VFP, 7, ARM_ISAR_VFPV2, "vsub"), - ATTR_SET_32_VFP_RRR (VDIV_VFP, 7, ARM_ISAR_VFPDIV, "vdiv"), - ATTR_SET_32_VFP_RRR (VFNMA_VFP, 7, ARM_ISAR_VFPFMAC, "vfnma"), - ATTR_SET_32_VFP_RRR (VFNMS_VFP, 7, ARM_ISAR_VFPFMAC, "vfnms"), - ATTR_SET_32_VFP_RRR (VFMA_VFP, 7, ARM_ISAR_VFPFMAC, "vfma"), - ATTR_SET_32_VFP_RRR (VFMS_VFP, 7, ARM_ISAR_VFPFMAC, "vfms"), - ATTR_SET_32_VFP_RI (VMOVI_VFP, 7, ARM_ISAR_VFPV3, "vmov"), - ATTR_SET_32_VFP_RR (VMOVR_VFP, 7, ARM_ISAR_VFPV2, "vmov"), - ATTR_SET_32_VFP_RR (VABS_VFP, 7, ARM_ISAR_VFPV2, "vabs"), - ATTR_SET_32_VFP_RR (VNEG_VFP, 7, ARM_ISAR_VFPV2, "vneg"), - ATTR_SET_32_VFP_RR (VSQRT_VFP, 7, ARM_ISAR_VFPSQRT, "vsqrt"), - ATTR_SET_32_VFP_RR_S_S2 (VCVTBFH_VFP, 7, ARM_ISAR_VFPHP, "vcvtb", 32, 16), - ATTR_SET_32_VFP_RR_S_S2 (VCVTTFH_VFP, 7, ARM_ISAR_VFPHP, "vcvtt", 32, 16), - ATTR_SET_32_VFP_RR_S_S2 (VCVTBHF_VFP, 7, ARM_ISAR_VFPHP, "vcvtb", 16, 32), - ATTR_SET_32_VFP_RR_S_S2 (VCVTTHF_VFP, 7, ARM_ISAR_VFPHP, "vcvtt", 16, 32), - ATTR_SET_32_VFP_RR (VCMP_VFP, 7, ARM_ISAR_VFPV2, "vcmp"), - ATTR_SET_32_VFP_RR (VCMPE_VFP, 7, ARM_ISAR_VFPV2, "vcmpe"), - ATTR_SET_32_VFP_R0 (VCMP0_VFP, 7, ARM_ISAR_VFPV2, "vcmp"), - ATTR_SET_32_VFP_R0 (VCMPE0_VFP, 7, ARM_ISAR_VFPV2, "vcmpe"), - ATTR_SET_32_VFP_LS_T (VCVTFU_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _U), - ATTR_SET_32_VFP_LS_T (VCVTFS_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _S), - ATTR_SET_32_VFP_RI_T2C (VCVTFXUH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _U16, 16), - ATTR_SET_32_VFP_RI_T2C (VCVTFXUW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _U32, 32), - ATTR_SET_32_VFP_RI_T2C (VCVTFXSH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _S16, 16), - ATTR_SET_32_VFP_RI_T2C (VCVTFXSW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _S32, 32), - ATTR_SET_32_VFP_NS_T (VCVTRUF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvtr", _U), - ATTR_SET_32_VFP_NS_T (VCVTUF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _U), - ATTR_SET_32_VFP_NS_T (VCVTRSF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvtr", _S), - ATTR_SET_32_VFP_NS_T (VCVTSF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _S), - ATTR_SET_32_VFP_RI_T2C (VCVTXFSH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _S16, _F32, 16), - ATTR_SET_32_VFP_RI_T2C (VCVTXFSW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _S32, _F32, 32), - ATTR_SET_32_VFP_RI_T2C (VCVTXFUH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _U16, _F32, 16), - ATTR_SET_32_VFP_RI_T2C (VCVTXFUW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _U32, _F32, 32), - - // Extension register load/store instructions - ATTR_SET_32_SDFP_LDSTM (VSTMIA, 7, ARM_ISAR_VMRS, "vstm"), - ATTR_SET_32_SDFP_LDSTM (VSTMIAW, 7, ARM_ISAR_VMRS, "vstm"), - ATTR_SET_32_SDFP_LDST (VSTR, 7, ARM_ISAR_VMRS, "vstr"), - ATTR_SET_32_SDFP_LDSTM (VSTMDBW, 7, ARM_ISAR_VMRS, "vstm"), - ATTR_SET_32_SDFP_PUSH (VPUSH, 7, ARM_ISAR_VMRS, "vpush"), - ATTR_SET_32_SDFP_LDSTM (VLDMIA, 7, ARM_ISAR_VMRS, "vldm"), - ATTR_SET_32_SDFP_LDSTM (VLDMIAW, 7, ARM_ISAR_VMRS, "vldm"), - ATTR_SET_32_SDFP_PUSH (VPOP, 7, ARM_ISAR_VMRS, "vpop"), - ATTR_SET_32_SDFP_LDST (VLDR, 7, ARM_ISAR_VMRS, "vldr"), - ATTR_SET_32_SDFP_LDSTM (VLDMDBW, 7, ARM_ISAR_VMRS, "vldm"), - - // 8, 16 and 32-bit transfer instructions between ARM core regs and extension regs - ATTR_SET_32_VMRS (VMRS, 7, ARM_ISAR_VMRS, "vmrs"), - ATTR_SET_32_VMSR (VMSR, 7, ARM_ISAR_VMRS, "vmsr"), - ATTR_SET_32_VMOVRS (VMOVRS, 7, ARM_ISAR_VMRS, "vmov"), - ATTR_SET_32_VMOVSR (VMOVSR, 7, ARM_ISAR_VMRS, "vmov"), - ATTR_SET_32_VMOVZR (VMOVZR, 7, ARM_ISAR_VMRS, "vmov"), - ATTR_SET_32_VMOVRZ (VMOVRZ, 7, ARM_ISAR_VMRS, "vmov"), - - // 64-bit transfer instructions between ARM core regs and extension regs - ATTR_SET_32_VMOVRRD (VMOVRRD, 7, ARM_ISAR_VMRS, "vmov"), - ATTR_SET_32_VMOVDRR (VMOVDRR, 7, ARM_ISAR_VMRS, "vmov"), - ATTR_SET_32_VMOVRRSS (VMOVRRSS, 7, ARM_ISAR_VMRS, "vmov"), - ATTR_SET_32_VMOVSSRR (VMOVSSRR, 7, ARM_ISAR_VMRS, "vmov"), - - //////////////////////////////////////////////////////////////////////////// - // terminator - //////////////////////////////////////////////////////////////////////////// - - // dummy entry for undecoded instruction - [TT_LAST] = {type:ARM_IT_LAST} -}; - - -//////////////////////////////////////////////////////////////////////////////// -// GENERIC DECODE TYPES -//////////////////////////////////////////////////////////////////////////////// - -// -// This type specifies the pattern for a decode table entry -// -typedef struct decodeEntryS { - armThumbType type :16; - Uns32 priority:16; - const char *name; - const char *pattern; -} decodeEntry; - - -//////////////////////////////////////////////////////////////////////////////// -// 16-BIT INSTRUCTION DECODE TABLE -//////////////////////////////////////////////////////////////////////////////// - -// -// Create the 16-bit Thumb instruction decode table -// -static vmidDecodeTableP createDecodeTableThumb16(void) { - - const static decodeEntry entries[] = { - - // data processing instructions - DECODE_SET_16_ADC (ADC, "010000|0101"), - DECODE_SET_16_ADD1 (ADD1, "0001110"), - DECODE_SET_16_ADD2 (ADD2, "00110"), - DECODE_SET_16_ADD1 (ADD3, "0001100"), - DECODE_SET_16_ADD4 (ADD4LL, "01000100|0|0"), - DECODE_SET_16_ADD4 (ADD4LH, "01000100|0|1"), - DECODE_SET_16_ADD4 (ADD4H, "01000100|1|."), - DECODE_SET_16_ADD2 (ADD5, "10100"), - DECODE_SET_16_ADD2 (ADD6, "10101"), - DECODE_SET_16_ADD7 (ADD7, "101100000"), - DECODE_SET_16_ADC (AND, "010000|0000"), - DECODE_SET_16_ASR1 (ASR1, "00010"), - DECODE_SET_16_ADC (ASR2, "010000|0100"), - DECODE_SET_16_ADC (BIC, "010000|1110"), - DECODE_SET_16_ADC (EOR, "010000|0001"), - DECODE_SET_16_ASR1 (LSL1, "00000"), - DECODE_SET_16_ADC (LSL2, "010000|0010"), - DECODE_SET_16_ASR1 (LSR1, "00001"), - DECODE_SET_16_ADC (LSR2, "010000|0011"), - DECODE_SET_16_ADD2 (MOV1, "00100"), - DECODE_SET_16_ADC (MOV2, "000000|0000"), - DECODE_SET_16_ADD4 (MOV3LL, "01000110|0|0"), - DECODE_SET_16_ADD4 (MOV3LH, "01000110|0|1"), - DECODE_SET_16_ADD4 (MOV3H, "01000110|1|."), - DECODE_SET_16_ADC (MVN, "010000|1111"), - DECODE_SET_16_ADC (NEG, "010000|1001"), - DECODE_SET_16_ADC (ORR, "010000|1100"), - DECODE_SET_16_ADC (ROR, "010000|0111"), - DECODE_SET_16_ADC (SBC, "010000|0110"), - DECODE_SET_16_ADD1 (SUB1, "0001111"), - DECODE_SET_16_ADD2 (SUB2, "00111"), - DECODE_SET_16_ADD1 (SUB3, "0001101"), - DECODE_SET_16_ADD7 (SUB4, "101100001"), - - // multiply instructions - DECODE_SET_16_ADC (MUL, "010000|1101"), - - // compare instructions - DECODE_SET_16_ADC (CMN, "010000|1011"), - DECODE_SET_16_ADD2 (CMP1, "00101"), - DECODE_SET_16_ADC (CMP2, "010000|1010"), - DECODE_SET_16_ADD4 (CMP3LH, "01000101|0|1"), - DECODE_SET_16_ADD4 (CMP3H, "01000101|1|."), - DECODE_SET_16_ADC (TST, "010000|1000"), - - // branch instructions - DECODE_SET_16_B1 (B1, "...."), - DECODE_SET_16_B2 (B2, "00"), - DECODE_SET_16_BLX2 (BLX2, "010001111"), - DECODE_SET_16_BLX2 (BX, "010001110"), - DECODE_SET_16_SWI (SWI, "1111"), - DECODE_SET_16_SWI (BU, "1110"), - - // miscellaneous instructions - DECODE_SET_16_BKPT (CPS, "0110011"), - DECODE_SET_16_BKPT (CBNZ, "10.1..."), - DECODE_SET_16_BKPT (CBZ, "00.1..."), - DECODE_SET_16_BKPT (SXTH, "001000."), - DECODE_SET_16_BKPT (SXTB, "001001."), - DECODE_SET_16_BKPT (UXTH, "001010."), - DECODE_SET_16_BKPT (UXTB, "001011."), - DECODE_SET_16_BKPT (REV, "101000."), - DECODE_SET_16_BKPT (REV16, "101001."), - DECODE_SET_16_BKPT (REVSH, "101011."), - DECODE_SET_16_BKPT (BKPT, "1110..."), - - // load and store instructions - DECODE_SET_16_ASR1 (LDR1, "01101"), - DECODE_SET_16_ADD1 (LDR2, "0101100"), - DECODE_SET_16_ADD2 (LDR3, "01001"), - DECODE_SET_16_ADD2 (LDR4, "10011"), - DECODE_SET_16_ASR1 (LDRB1, "01111"), - DECODE_SET_16_ADD1 (LDRB2, "0101110"), - DECODE_SET_16_ASR1 (LDRH1, "10001"), - DECODE_SET_16_ADD1 (LDRH2, "0101101"), - DECODE_SET_16_ADD1 (LDRSB, "0101011"), - DECODE_SET_16_ADD1 (LDRSH, "0101111"), - DECODE_SET_16_ASR1 (STR1, "01100"), - DECODE_SET_16_ADD1 (STR2, "0101000"), - DECODE_SET_16_ADD2 (STR3, "10010"), - DECODE_SET_16_ASR1 (STRB1, "01110"), - DECODE_SET_16_ADD1 (STRB2, "0101010"), - DECODE_SET_16_ASR1 (STRH1, "10000"), - DECODE_SET_16_ADD1 (STRH2, "0101001"), - - // load and store multiple instructions - DECODE_SET_16_ADD2 (LDMIA, "11001"), - DECODE_SET_16_POP (POP, "1011110"), - DECODE_SET_16_POP (PUSH, "1011010"), - DECODE_SET_16_ADD2 (STMIA, "11000"), - - // if-then and hints - DECODE_SET_16_IT (IT, "....", "...."), - DECODE_SET_16_HINT1 (NOP, "....", "0000"), - DECODE_SET_16_HINT2 (YIELD, "0001", "0000"), - DECODE_SET_16_HINT2 (WFE, "0010", "0000"), - DECODE_SET_16_HINT2 (WFI, "0011", "0000"), - DECODE_SET_16_HINT2 (SEV, "0100", "0000"), - - // terminator - {0} - }; - - // create the table - vmidDecodeTableP table = vmidNewDecodeTable(16, TT_LAST); - const decodeEntry *entry; - - // add all entries to the decode table - for(entry=entries; entry->pattern; entry++) { - vmidNewEntryFmtBin( - table, - entry->name, - entry->type, - entry->pattern, - entry->priority - ); - } - - return table; -} - -// -// Create the 32-bit Thumb instruction decode table -// -static vmidDecodeTableP createDecodeTableThumb32(void) { - - const static decodeEntry entries[] = { - - // data processing - DECODE_SET_32_AND (AND, "0000"), - DECODE_SET_32_TST (TST, "0000"), - DECODE_SET_32_AND (BIC, "0001"), - DECODE_SET_32_AND (ORR, "0010"), - DECODE_SET_32_MOV (MOV, "0010"), - DECODE_SET_32_AND (ORN, "0011"), - DECODE_SET_32_MOV (MVN, "0011"), - DECODE_SET_32_AND (EOR, "0100"), - DECODE_SET_32_TST (TEQ, "0100"), - DECODE_SET_32_AND (ADD, "1000"), - DECODE_SET_32_TST (CMN, "1000"), - DECODE_SET_32_AND (ADC, "1010"), - DECODE_SET_32_AND (SBC, "1011"), - DECODE_SET_32_AND (SUB, "1101"), - DECODE_SET_32_TST (CMP, "1101"), - DECODE_SET_32_AND (RSB, "1110"), - - // pack halfword - DECODE_SET_32_PKHBT (PKHBT, "0"), - DECODE_SET_32_PKHBT (PKHTB, "1"), - - // data processing (plain binary immediate) - DECODE_SET_32_ADD_PI (ADD_PI, "00000"), - DECODE_SET_32_ADR_PI (ADD_ADR_PI, "00000"), - DECODE_SET_32_ADD_PI (SUB_PI, "01010"), - DECODE_SET_32_ADR_PI (SUB_ADR_PI, "01010"), - DECODE_SET_32_ADD_PI (MOV_PI, "00100"), - DECODE_SET_32_ADD_PI (MOVT_PI, "01100"), - DECODE_SET_32_ADD_PI (SSAT, "100.0"), - DECODE_SET_32_SSAT16 (SSAT16, "10010"), - DECODE_SET_32_ADD_PI (SBFX, "10100"), - DECODE_SET_32_ADD_PI (BFI, "10110"), - DECODE_SET_32_BFC (BFC, "10110"), - DECODE_SET_32_ADD_PI (UBFX, "11100"), - DECODE_SET_32_ADD_PI (USAT, "110.0"), - DECODE_SET_32_SSAT16 (USAT16, "11010"), - - // data processing (register) - DECODE_SET_32_LSL (LSL, "000.", "0000", "...."), - DECODE_SET_32_LSL (LSR, "001.", "0000", "...."), - DECODE_SET_32_LSL (ASR, "010.", "0000", "...."), - DECODE_SET_32_LSL (ROR, "011.", "0000", "...."), - DECODE_SET_32_LSL (SXTAH, "0000", "1...", "...."), - DECODE_SET_32_SXTH (SXTH, "0000", "1...", "1111"), - DECODE_SET_32_LSL (UXTAH, "0001", "1...", "...."), - DECODE_SET_32_SXTH (UXTH, "0001", "1...", "1111"), - DECODE_SET_32_LSL (SXTAB16, "0010", "1...", "...."), - DECODE_SET_32_SXTH (SXTB16, "0010", "1...", "1111"), - DECODE_SET_32_LSL (UXTAB16, "0011", "1...", "...."), - DECODE_SET_32_SXTH (UXTB16, "0011", "1...", "1111"), - DECODE_SET_32_LSL (SXTAB, "0100", "1...", "...."), - DECODE_SET_32_SXTH (SXTB, "0100", "1...", "1111"), - DECODE_SET_32_LSL (UXTAB, "0101", "1...", "...."), - DECODE_SET_32_SXTH (UXTB, "0101", "1...", "1111"), - - // parallel add/subtract instructions - DECODE_SET_32_PAS (ADD16, "001"), - DECODE_SET_32_PAS (ASX, "010"), - DECODE_SET_32_PAS (SAX, "110"), - DECODE_SET_32_PAS (SUB16, "101"), - DECODE_SET_32_PAS (ADD8, "000"), - DECODE_SET_32_PAS (SUB8, "100"), - - // miscellaneous operation instructions - DECODE_SET_32_LSL (QADD, "1000", "1000", "...."), - DECODE_SET_32_LSL (QDADD, "1000", "1001", "...."), - DECODE_SET_32_LSL (QSUB, "1000", "1010", "...."), - DECODE_SET_32_LSL (QDSUB, "1000", "1011", "...."), - DECODE_SET_32_LSL (REV, "1001", "1000", "...."), - DECODE_SET_32_LSL (REV16, "1001", "1001", "...."), - DECODE_SET_32_LSL (RBIT, "1001", "1010", "...."), - DECODE_SET_32_LSL (REVSH, "1001", "1011", "...."), - DECODE_SET_32_LSL (SEL, "1010", "1000", "...."), - DECODE_SET_32_LSL (CLZ, "1011", "1000", "...."), - - // multiply, multiply accumulate and absolute difference instructions - DECODE_SET_32_MLA (MLA, "0000", "0000"), - DECODE_SET_32_MUL (MUL, "0000", "0000"), - DECODE_SET_32_MLA (MLS, "0000", "0001"), - DECODE_SET_32_MLA (SDIV, "1001", "1111"), - DECODE_SET_32_MLA (UDIV, "1011", "1111"), - DECODE_SET_32_SMLA_XY (SMLA, "0001", "00" ), - DECODE_SET_32_SMUL_XY (SMUL, "0001", "00" ), - DECODE_SET_32_SMLAD (SMLAD, "0010", "000" ), - DECODE_SET_32_SMUAD (SMUAD, "0010", "000" ), - DECODE_SET_32_SMLAW (SMLAW, "0011", "000" ), - DECODE_SET_32_SMULW (SMULW, "0011", "000" ), - DECODE_SET_32_SMLAD (SMLSD, "0100", "000" ), - DECODE_SET_32_SMUAD (SMUSD, "0100", "000" ), - DECODE_SET_32_SMMLA (SMMLA, "0101", "000" ), - DECODE_SET_32_SMMUL (SMMUL, "0101", "000" ), - DECODE_SET_32_SMMLA (SMMLS, "0110", "000" ), - DECODE_SET_32_MUL (USAD8, "0111", "0000"), - DECODE_SET_32_MLA (USADA8, "0111", "0000"), - DECODE_SET_32_MLA (SMLAL, "1100", "0000"), - DECODE_SET_32_MLA (SMULL, "1000", "0000"), - DECODE_SET_32_MLA (UMAAL, "1110", "0110"), - DECODE_SET_32_MLA (UMLAL, "1110", "0000"), - DECODE_SET_32_MLA (UMULL, "1010", "0000"), - DECODE_SET_32_SMLA_XY (SMLAL, "1100", "10" ), - DECODE_SET_32_SMLAD (SMLALD, "1100", "110" ), - DECODE_SET_32_SMLAD (SMLSLD, "1101", "110" ), - - // branch and miscellaneous control instructions - DECODE_SET_32_B1 (B1, "0.0", "."), - DECODE_SET_32_B1 (B2, "0.1", "."), - DECODE_SET_32_B1 (BL, "1.1", "."), - DECODE_SET_32_MSR (MSR, "0.0", "011100."), - DECODE_SET_32_HINT1 (NOP, "0.0", "0111010", "........"), - DECODE_SET_32_HINT2 (YIELD, "0.0", "0111010", "00000001"), - DECODE_SET_32_HINT2 (WFE, "0.0", "0111010", "00000010"), - DECODE_SET_32_HINT2 (WFI, "0.0", "0111010", "00000011"), - DECODE_SET_32_HINT2 (SEV, "0.0", "0111010", "00000100"), - DECODE_SET_32_HINT2 (DBG, "0.0", "0111010", "1111...."), - DECODE_SET_32_MSR (MRS, "0.0", "011111."), - DECODE_SET_32_UNDEF (UNDEF, "0.0", ".111..."), - DECODE_SET_32_CLREX (CLREX, "0010"), - DECODE_SET_32_CLREX (DSB, "0100"), - DECODE_SET_32_CLREX (DMB, "0101"), - DECODE_SET_32_CLREX (ISB, "0110"), - - // load and store multiple instructions - DECODE_SET_32_SRS (STMDB, "10", ".0...."), - DECODE_SET_32_SRS (STMIA, "01", ".0...."), - DECODE_SET_32_SRS (LDMDB, "10", ".1...."), - DECODE_SET_32_SRS (LDMIA, "01", ".1...."), - DECODE_SET_32_POPM (POPM, "01", "111101"), - DECODE_SET_32_POPM (PUSHM, "10", "101101"), - - // dual and exclusive instructions - DECODE_SET_32_LDRD_IMM (LDRD_IMM, "0.", "11", "...."), - DECODE_SET_32_LDRD_IMM (LDRD_IMM, "1.", ".1", "...."), - DECODE_SET_32_LDRD_IMM (STRD_IMM, "0.", "10", "...."), - DECODE_SET_32_LDRD_IMM (STRD_IMM, "1.", ".0", "...."), - DECODE_SET_32_LDREX (LDREX, "00", "01", "...."), - DECODE_SET_32_LDREX (LDREXB, "01", "01", "0100"), - DECODE_SET_32_LDREX (LDREXH, "01", "01", "0101"), - DECODE_SET_32_LDREX (STREX, "00", "00", "...."), - DECODE_SET_32_LDREX (STREXB, "01", "00", "0100"), - DECODE_SET_32_LDREX (STREXH, "01", "00", "0101"), - DECODE_SET_32_LDREX (TBB, "01", "01", "0000"), - DECODE_SET_32_LDREX (TBH, "01", "01", "0001"), - - // load instructions - DECODE_SET_32_LDR (LDR, "0", "10"), - DECODE_SET_32_LDR (LDRH, "0", "01"), - DECODE_SET_32_LDR (LDRB, "0", "00"), - DECODE_SET_32_LDR (LDRSH, "1", "01"), - DECODE_SET_32_LDR (LDRSB, "1", "00"), - DECODE_SET_32_STR (STR, "0", "10"), - DECODE_SET_32_STR (STRH, "0", "01"), - DECODE_SET_32_STR (STRB, "0", "00"), - DECODE_SET_32_PLD (PLD, "0", "00"), - DECODE_SET_32_PLD (PLI, "1", "00"), - DECODE_SET_32_UHINTH (UHINTH, "01"), - DECODE_SET_32_UHINTH (UHINTB, "00"), - - // coprocessor instructions - DECODE_SET_32_CDP (CDP ), - DECODE_SET_32_CDP2 (CDP2 ), - DECODE_SET_32_LDC (LDC, "1"), - DECODE_SET_32_LDC2 (LDC2, "1"), - DECODE_SET_32_MCR (MCR, "0"), - DECODE_SET_32_MCR2 (MCR2, "0"), - DECODE_SET_32_MCR (MRC, "1"), - DECODE_SET_32_MCR2 (MRC2, "1"), - DECODE_SET_32_LDC (STC, "0"), - DECODE_SET_32_LDC2 (STC2, "0"), - DECODE_SET_32_MCRR (MCRR, "0"), - DECODE_SET_32_MCRR2 (MCRR2, "0"), - DECODE_SET_32_MCRR (MRRC, "1"), - DECODE_SET_32_MCRR2 (MRRC2, "1"), - - // VFP data processing instructions - DECODE_SET_32_VFP_S (VMLA_VFP, "0.00", "....", ".0"), - DECODE_SET_32_VFP_S (VMLS_VFP, "0.00", "....", ".1"), - DECODE_SET_32_VFP_S (VNMLS_VFP, "0.01", "....", ".0"), - DECODE_SET_32_VFP_S (VNMLA_VFP, "0.01", "....", ".1"), - DECODE_SET_32_VFP_S (VMUL_VFP, "0.10", "....", ".0"), - DECODE_SET_32_VFP_S (VNMUL_VFP, "0.10", "....", ".1"), - DECODE_SET_32_VFP_S (VADD_VFP, "0.11", "....", ".0"), - DECODE_SET_32_VFP_S (VSUB_VFP, "0.11", "....", ".1"), - DECODE_SET_32_VFP_S (VDIV_VFP, "1.00", "....", ".0"), - // Note: Arm docs wrong: op=1 is VFNMA, not VFNMS - DECODE_SET_32_VFP_S (VFNMA_VFP, "1.01", "....", ".1"), - DECODE_SET_32_VFP_S (VFNMS_VFP, "1.01", "....", ".0"), - DECODE_SET_32_VFP_S (VFMA_VFP, "1.10", "....", ".0"), - DECODE_SET_32_VFP_S (VFMS_VFP, "1.10", "....", ".1"), - DECODE_SET_32_VFP_S (VMOVI_VFP, "1.11", "....", ".0"), - DECODE_SET_32_VFP_S (VMOVR_VFP, "1.11", "0000", "01"), - DECODE_SET_32_VFP_S (VABS_VFP, "1.11", "0000", "11"), - DECODE_SET_32_VFP_S (VNEG_VFP, "1.11", "0001", "01"), - DECODE_SET_32_VFP_S (VSQRT_VFP, "1.11", "0001", "11"), - DECODE_SET_32_VFP_S (VCVTBFH_VFP, "1.11", "0010", "01"), - DECODE_SET_32_VFP_S (VCVTTFH_VFP, "1.11", "0010", "11"), - DECODE_SET_32_VFP_S (VCVTBHF_VFP, "1.11", "0011", "01"), - DECODE_SET_32_VFP_S (VCVTTHF_VFP, "1.11", "0011", "11"), - DECODE_SET_32_VFP_S (VCMP_VFP, "1.11", "0100", "01"), - DECODE_SET_32_VFP_S (VCMPE_VFP, "1.11", "0100", "11"), - DECODE_SET_32_VFP_S (VCMP0_VFP, "1.11", "0101", "01"), - DECODE_SET_32_VFP_S (VCMPE0_VFP, "1.11", "0101", "11"), - DECODE_SET_32_VFP_S (VCVTFU_VFP, "1.11", "1000", "01"), - DECODE_SET_32_VFP_S (VCVTFS_VFP, "1.11", "1000", "11"), - DECODE_SET_32_VFP_S (VCVTFXSH_VFP, "1.11", "1010", "01"), - DECODE_SET_32_VFP_S (VCVTFXSW_VFP, "1.11", "1010", "11"), - DECODE_SET_32_VFP_S (VCVTFXUH_VFP, "1.11", "1011", "01"), - DECODE_SET_32_VFP_S (VCVTFXUW_VFP, "1.11", "1011", "11"), - DECODE_SET_32_VFP_S (VCVTRUF_VFP, "1.11", "1100", "01"), - DECODE_SET_32_VFP_S (VCVTUF_VFP, "1.11", "1100", "11"), - DECODE_SET_32_VFP_S (VCVTRSF_VFP, "1.11", "1101", "01"), - DECODE_SET_32_VFP_S (VCVTSF_VFP, "1.11", "1101", "11"), - DECODE_SET_32_VFP_S (VCVTXFSH_VFP, "1.11", "1110", "01"), - DECODE_SET_32_VFP_S (VCVTXFSW_VFP, "1.11", "1110", "11"), - DECODE_SET_32_VFP_S (VCVTXFUH_VFP, "1.11", "1111", "01"), - DECODE_SET_32_VFP_S (VCVTXFUW_VFP, "1.11", "1111", "11"), - - // Extension register load/store instructions - DECODE_SET_32_SDFP_LDST (VSTMIA, "01.00"), - DECODE_SET_32_SDFP_LDST (VSTMIAW, "01.10"), - DECODE_SET_32_SDFP_LDST (VSTR, "1..00"), - DECODE_SET_32_SDFP_LDST (VSTMDBW, "10.10"), - DECODE_SET_32_SDFP_PUSH_POP (VPUSH, "10.10"), - DECODE_SET_32_SDFP_LDST (VLDMIA, "01.01"), - DECODE_SET_32_SDFP_LDST (VLDMIAW, "01.11"), - DECODE_SET_32_SDFP_PUSH_POP (VPOP, "01.11"), - DECODE_SET_32_SDFP_LDST (VLDR, "1..01"), - DECODE_SET_32_SDFP_LDST (VLDMDBW, "10.11"), - - // 8, 16 and 32-bit transfer instructions between ARM core regs and extension regs - DECODE_SET_32_VMRS (VMRS, "1", "0", "111", ".."), - DECODE_SET_32_VMRS (VMSR, "0", "0", "111", ".."), - DECODE_SET_32_VMRS (VMOVRS, "1", "0", "000", ".."), - DECODE_SET_32_VMRS (VMOVSR, "0", "0", "000", ".."), - DECODE_SET_32_VMRS (VMOVRZ, "1", "1", "00.", "00"), - DECODE_SET_32_VMRS (VMOVZR, "0", "1", "00.", "00"), - - // 64-bit transfer instructions between ARM core regs and extension regs - DECODE_SET_32_VMOVRRD (VMOVRRD, "1", "1", "00.1"), - DECODE_SET_32_VMOVRRD (VMOVDRR, "0", "1", "00.1"), - DECODE_SET_32_VMOVRRD (VMOVRRSS, "1", "0", "00.1"), - DECODE_SET_32_VMOVRRD (VMOVSSRR, "0", "0", "00.1"), - - // terminator - {0} - }; - - // create the table - vmidDecodeTableP table = vmidNewDecodeTable(32, TT_LAST); - const decodeEntry *entry; - - // add all entries to the decode table - for(entry=entries; entry->pattern; entry++) { - vmidNewEntryFmtBin( - table, - entry->name, - entry->type, - entry->pattern, - entry->priority - ); - } - - return table; -} - -// -// Get the 16-bit Thumb instruction decode table -// -static vmidDecodeTableP getDecodeTableThumb16(void) { - - static vmidDecodeTableP table; - - if(!table) { - table = createDecodeTableThumb16(); - } - - return table; -} - -// -// Get the 32-bit Thumb instruction decode table -// -static vmidDecodeTableP getDecodeTableThumb32(void) { - - static vmidDecodeTableP table; - - if(!table) { - table = createDecodeTableThumb32(); - } - - return table; -} - -// -// Return effect that the instruction has on the flags (note that this may -// depend on whether the instruction is in an if-then block) -// -static armSetFlags getSetFlagsThumb(armP arm, Uns32 instr, armSetFlags sf) { - - armSetFlags result; - - switch(sf) { - - case SF_0: - result = ARM_SF_0; - break; - - case SF_V: - result = ARM_SF_V; - break; - - case SF_I: - result = ARM_SF_I; - break; - - case SF_20_V: - result = OP_F20(instr) ? ARM_SF_V : ARM_SF_0; - break; - - case SF_IT: - if(arm->itStateMT) { - result = ARM_SF_0; - } else if(arm->UAL) { - result = ARM_SF_V; - } else { - result = ARM_SF_I; - } - break; - - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -// -// Return condition associated with the instruction (note that this may depend -// on whether the instruction is in an if-then block) -// -static armCondition getConditionThumb(armP arm, Uns32 instr, condSpec cond) { - - armCondition result = ARM_C_AL; - - if(arm->itStateMT) { - result = arm->itStateMT>>4; - } else switch(cond) { - case CO_NA: break; - case CO_8: result = OP_COND_8(instr); break; - case CO_22: result = OP_COND_22(instr); break; - case CO_28: result = OP_COND_28(instr); break; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -// -// Return register index encoded in the Thumb instruction -// -static Uns8 getRegisterThumb(Uns32 instr, rSpec r) { - - Uns8 result = 0; - - switch(r) { - case R_NA: break; - case R3_0: result = OP_R3_0(instr); break; - case R3_3: result = OP_R3_3(instr); break; - case R3_6: result = OP_R3_6(instr); break; - case R3_8: result = OP_R3_8(instr); break; - case R4_0: result = OP_R4_0(instr); break; - case R4_8: result = OP_R4_8(instr); break; - case R4_12: result = OP_R4_12(instr); break; - case R4_16: result = OP_R4_16(instr); break; - case R4_0H7: result = OP_R4_0_H7(instr); break; - case R4_3H6: result = OP_R4_3_H6(instr); break; - case R_PC: result = ARM_REG_PC; break; - case R_SP: result = ARM_REG_SP; break; - case R_LR: result = ARM_REG_LR; break; - case V_0_5: result = OP_V0_5(instr); break; - case V_16_7: result = OP_V16_7(instr); break; - case V_12_22: result = OP_V12_22(instr); break; - case V_5_0: result = OP_V5_0(instr); break; - case V_22_12: result = OP_V22_12(instr); break; - case V_7_16: result = OP_V7_16(instr); break; - case V3_0: result = OP_U_3_0(instr); break; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -/// -// Return shift operation encoded in the Thumb instruction -// -static armShiftOp getShiftOpThumb(Uns32 instr, shiftSpec ss) { - - Uns32 result = ARM_SO_NA; - - const static armShiftOp shiftMap[] = { - ARM_SO_LSL, ARM_SO_LSR, ARM_SO_ASR, ARM_SO_ROR - }; - - switch(ss) { - case SS_NA: - break; - case SS_ASR: - result = ARM_SO_ASR; - break; - case SS_LSL: - result = ARM_SO_LSL; - break; - case SS_LSR: - result = ARM_SO_LSR; - break; - case SS_ROR: - result = ARM_SO_ROR; - break; - case SS_RRX: - result = ARM_SO_RRX; - break; - case SS2_4: - result = shiftMap[OP_U_2_4(instr)]; - break; - case SS2_20: - result = shiftMap[OP_U_2_20(instr)]; - break; - case SS2_21: - result = shiftMap[OP_U_2_21(instr)]; - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -// -// Allow for cases where constant value of zero is interpreted as 32 -// -static Uns32 adjustShift(Uns32 result, constSpec c, armShiftOp so) { - - if((result==0) && (c!=CS_NA) && ((so==ARM_SO_LSR) || (so==ARM_SO_ASR))) { - result = 32; - } - - return result; -} - -// -// Return a 5-bit plain immediate constant encoded within the Thumb instruction -// -static Uns32 plainImmediateThumb5(Uns32 instr) { - - // bitfield to extract instruction parts - union { - Uns32 instr; - struct { - Uns32 _u1 : 6; - Uns32 imm2 : 2; - Uns32 _u2 : 4; - Uns32 imm3 : 3; - Uns32 _u3 : 17; - } f; - } u1 = {instr}; - - // compose result - return ((u1.f.imm3)<<2) | u1.f.imm2; -} - -// -// Return a 12-bit plain immediate constant encoded within the Thumb instruction -// -static Uns32 plainImmediateThumb12(Uns32 instr) { - - // bitfield to extract instruction parts - union { - Uns32 instr; - struct { - Uns32 imm8 : 8; - Uns32 _u1 : 4; - Uns32 imm3 : 3; - Uns32 _u2 : 11; - Uns32 i : 1; - Uns32 _u3 : 5; - } f; - } u1 = {instr}; - - // compose result - return ((u1.f.i)<<11) | ((u1.f.imm3)<<8) | u1.f.imm8; -} - -// -// Return a 16-bit plain immediate constant encoded within the Thumb instruction -// -static Uns32 plainImmediateThumb16(Uns32 instr) { - - // bitfield to extract instruction parts - union { - Uns32 instr; - struct { - Uns32 imm8 : 8; - Uns32 _u1 : 4; - Uns32 imm3 : 3; - Uns32 _u2 : 1; - Uns32 imm4 : 4; - Uns32 _u3 : 6; - Uns32 i : 1; - Uns32 _u4 : 5; - } f; - } u1 = {instr}; - - // compose result - return ((u1.f.imm4)<<12) | ((u1.f.i)<<11) | ((u1.f.imm3)<<8) | u1.f.imm8; -} - -// -// Return a modified immediate constant encoded within the Thumb instruction -// and set byref 'crotate' to any constant rotation -// -static Uns32 modifiedImmediateThumb(Uns32 instr, Uns8 *crotate) { - - Uns32 result; - - // bitfield to extract instruction parts - union { - Uns32 instr; - struct { - Uns32 bcdefgh : 7; - Uns32 a : 1; - Uns32 _u1 : 4; - Uns32 imm3 : 3; - Uns32 _u2 : 11; - Uns32 i : 1; - Uns32 _u3 : 5; - } f; - } u1 = {instr}; - - // compose code - Uns32 code = ((u1.f.i)<<4) | ((u1.f.imm3)<<1) | u1.f.a; - Uns32 abcdefgh = (u1.f.a<<7) | u1.f.bcdefgh; - - // derive result from code - switch(code) { - - case 0x00: case 0x01: - result = abcdefgh; - break; - - case 0x02: case 0x03: - result = (abcdefgh<<16) | abcdefgh; - break; - - case 0x04: case 0x05: - result = (abcdefgh<<24) | (abcdefgh<<8); - break; - - case 0x06: case 0x07: - result = (abcdefgh<<24) | (abcdefgh<<16) | (abcdefgh<<8) | abcdefgh; - break; - - default: { - Uns32 shift = 32-code; - result = (1<<7) | u1.f.bcdefgh; - result <<= shift; - *crotate = code; - break; - } - } - - return result; -} - -// -// Negate the argument if U bit of Thumb instruction is zero -// -inline static Uns32 negateIfU(armInstructionInfoP info, Uns32 result) { - return info->u ? result : -result; -} - -// -// Return a constant encoded within the Thumb instruction and set byref -// 'crotate' to any constant rotation -// -static Uns32 getConstantThumb( - armP arm, - armInstructionInfoP info, - Uns32 instr, - constSpec c, - armShiftOp so, - Uns8 *crotate -) { - Uns32 result = 0; - - // assume constant rotation is zero - *crotate = 0; - - switch(c) { - case CS_NA: - break; - case CS_U_2_4: - result = OP_U_2_4(instr); - break; - case CS_U_2_4x8: - result = OP_U_2_4(instr)*8; - break; - case CS_U_2_10: - result = OP_U_2_10(instr); - break; - case CS_U_3_6: - result = OP_U_3_6(instr); - break; - case CS_U_4_4: - result = OP_U_4_4(instr); - break; - case CS_U_4_0: - result = OP_U_4_0(instr); - break; - case CS_U_5_6: - result = OP_U_5_6(instr); - break; - case CS_U_5_6_SZ: - result = OP_U_5_6(instr)*info->sz; - break; - case CS_U_5_0_5M16: - result = OP_U_5_0_5(instr); - result = 16 - (result > 16 ? 0 : result); - break; - case CS_U_5_0_5M32: - result = 32 - OP_U_5_0_5(instr); - break; - case CS_U_7_0x4: - result = OP_U_7_0(instr)*4; - break; - case CS_U_8_0: - result = OP_U_8_0(instr); - break; - case CS_U_8_0_U: - result = negateIfU(info, OP_U_8_0(instr)); - break; - case CS_U_8_0_SZ: - result = OP_U_8_0(instr)*info->sz; - break; - case CS_U_8_0x4_U: - result = negateIfU(info, OP_U_8_0(instr)*4); - break; - case CS_U_8_0x4: - result = OP_U_8_0(instr)*4; - break; - case CS_U_12_0: - result = OP_U_12_0(instr); - break; - case CS_U_12_0_U: - result = negateIfU(info, OP_U_12_0(instr)); - break; - case CS_PI5: - result = plainImmediateThumb5(instr); - break; - case CS_PI12: - result = plainImmediateThumb12(instr); - break; - case CS_PI16: - result = plainImmediateThumb16(instr); - break; - case CS_MI: - result = modifiedImmediateThumb(instr, crotate); - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - // allow for cases where constant value of zero is interpreted as 32 - return adjustShift(result, c, so); -} - -// -// Return nregs, fixed or encoded within the Thumb instruction -// -static Uns8 getNRegsThumb(Uns32 instr, nregSpec nRegs) { - - Uns8 result = 0; - - switch(nRegs) { - case NREG_NA: - break; - case NREG_7_1: - result = OP_U_7_1(instr); - break; - case NREG_8_0: - result = OP_U_8_0(instr); - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -// -// Return bit operation width encoded in the ARM instruction -// -static Int8 getWidthThumb(Uns32 instr, widthSpec w) { - - Int8 result = 0; - - switch(w) { - case WS_NA: - break; - case WS_WIDTH4: - result = OP_U_4_0(instr); - break; - case WS_WIDTH4M1: - result = OP_U_4_0(instr)+1; - break; - case WS_WIDTH5: - result = OP_U_5_0(instr); - break; - case WS_WIDTH5M1: - result = OP_U_5_0(instr)+1; - break; - case WS_MSB: - result = OP_U_5_0(instr)-plainImmediateThumb5(instr)+1; - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -// -// Get post-indexed attributes for the Thumb instruction -// -static Bool getPostIndexedThumb(Uns32 instr, postIndexSpec pi) { - - Bool result = False; - - switch(pi) { - case PI_0: - result = False; - break; - case PI_1: - result = True; - break; - case PI_10: - result = !OP_PI_10(instr); - break; - case PI_24: - result = !OP_PI_24(instr); - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -// -// Get writeback attributes for the Thumb instruction -// -static Bool getWritebackThumb( - Uns32 instr, - writebackSpec wb, - Uns32 base, - Uns32 rList -) { - Bool result = False; - - switch(wb) { - case WB_0: - result = False; - break; - case WB_1: - result = True; - break; - case WB_1_NB: - result = !(rList & (1<thisPC + displacement; -} - -// -// Return a 20-bit target address encoded within the Thumb instruction -// -static Uns32 getTarget20(armInstructionInfoP info, Uns32 instr) { - - // bitfield to extract instruction parts - union { - Uns32 instr; - struct { - Uns32 imm11 : 11; - Uns32 j2 : 1; - Uns32 _u1 : 1; - Uns32 j1 : 1; - Uns32 _u2 : 2; - Uns32 imm6 : 6; - Uns32 _u3 : 4; - Uns32 s : 1; - Uns32 _u4 : 5; - } f; - } u1 = {instr}; - - // bitfield to compose target - union { - Uns32 offset; - struct { - Uns32 zero : 1; - Uns32 imm11 : 11; - Uns32 imm6 : 6; - Uns32 j2 : 1; - Uns32 j1 : 1; - Uns32 s : 12; - } f; - } u2; - - // fill target fields; - u2.f.zero = 0; - u2.f.imm11 = u1.f.imm11; - u2.f.imm6 = u1.f.imm6; - u2.f.j2 = u1.f.j2; - u2.f.j1 = u1.f.j1; - u2.f.s = -u1.f.s; - - // return target address - return getTarget(info, u2.offset+4); -} - -// -// Return a 24-bit target address encoded within the Thumb instruction -// -static Uns32 getTarget24(armInstructionInfoP info, Uns32 instr) { - - // bitfield to extract instruction parts - union { - Uns32 instr; - struct { - Uns32 imm11 : 11; - Uns32 j2 : 1; - Uns32 _u1 : 1; - Uns32 j1 : 1; - Uns32 _u2 : 2; - Uns32 imm10 : 10; - Uns32 s : 1; - Uns32 _u3 : 5; - } f; - } u1 = {instr}; - - // bitfield to compose target - union { - Uns32 offset; - struct { - Uns32 zero : 1; - Uns32 imm11 : 11; - Uns32 imm10 : 10; - Uns32 i2 : 1; - Uns32 i1 : 1; - Uns32 s : 8; - } f; - } u2; - - // compose i1 and i2 fields; - Uns32 s = u1.f.s; - Uns32 i1 = !(u1.f.j1 ^ s); - Uns32 i2 = !(u1.f.j2 ^ s); - - // fill target fields; - u2.f.zero = 0; - u2.f.imm11 = u1.f.imm11; - u2.f.imm10 = u1.f.imm10; - u2.f.i2 = i2; - u2.f.i1 = i1; - u2.f.s = -s; - - // return target address - return getTarget(info, u2.offset+4); -} - -// -// Return a target address encoded within the Thumb instruction -// -static Uns32 getTargetThumb( - armInstructionInfoP info, - Uns32 instr, - targetSpec t -) { - Uns32 result = 0; - - switch(t) { - case TC_NA: - break; - case TC_S8: - result = getTarget(info, OP_TS8(instr)+4); - break; - case TC_S11: - result = getTarget(info, OP_TS11(instr)+4); - break; - case TC_S20_T2: - result = getTarget20(info, instr); - break; - case TC_S24_T2: - result = getTarget24(info, instr); - break; - case TC_U9_7_3: - result = getTarget(info, OP_TU9_7_3(instr)+4); - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -// -// Return coprocessor opcode1 encoded within the Thumb instruction -// -static Uns32 getCpOp1Thumb( - armP arm, - armInstructionInfoP info, - Uns32 instr, - cpOp1Spec cpOp1 -) { - Uns32 result = 0; - - switch(cpOp1) { - case COP_NA: break; - case COP_4_4: result = OP_CPOP1_4_4(instr); break; - case COP_4_20: result = OP_CPOP1_4_20(instr); break; - case COP_3_21: result = OP_CPOP1_3_21(instr); break; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -// -// Return register list encoded within the Thumb instruction -// -static Uns32 getRListThumb(Uns32 instr, rListSpec rList) { - - Uns32 result = 0; - - switch(rList) { - case RL_NA: break; - case RL_16: result = OP_RL_16(instr); break; - case RL_16_LR: result = OP_RL_16_LR(instr); break; - case RL_16_PC: result = OP_RL_16_PC(instr); break; - case RL_32_SP: result = OP_RL_32_SP(instr); break; - case RL_32_PCSP: result = OP_RL_32_PCSP(instr); break; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -// -// Return increment/decrement action encoded within the Thumb instruction -// -static armIncDec getIncDecThumb( - armInstructionInfoP info, - armP arm, - Uns32 instr, - incDecSpec incDec -) { - armIncDec result = ARM_ID_NA; - - switch (incDec) { - case ID_NA: break; - case ID_DB: result = ARM_ID_DB; break; - case ID_IA: result = ARM_ID_IA; break; - case ID_DB_I: result = ARM_ID_DBI; break; - case ID_IA_I: result = ARM_ID_IAI; break; - case ID_U_P: - case ID_U_P_IMP: - case ID_U_P_IAI: { - armIncDec USpec = OP_U (instr) ? ARM_ID_I : ARM_ID_D; - armIncDec PSpec = OP_PI(instr) ? ARM_ID_B : ARM_ID_A; - - result = (ARM_ID_P | USpec | PSpec); - - if (incDec==ID_U_P_IMP) { - // inc/dec spec is always implicit (VPUSH/VPOP) - result |= ARM_ID_NS; - } else if(arm->UAL && (result==ARM_ID_IA) && (incDec==ID_U_P_IAI)) { - // inc/dec spec is implicit in UAL mode when it is IA - result |= ARM_ID_NS; - } - break; - } - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -// -// Return indication of whether Thumb instruction enables or disables interrupts -// (CPS) -// -static armFlagAction getFlagActionThumb( - armInstructionInfoP info, - imodSpec imod, - Uns32 instr -) { - armFlagAction result = ARM_FACT_NA; - - switch(imod) { - case IS_NA: break; - case IS_4: result = OP_IS_4(instr) ? ARM_FACT_ID : ARM_FACT_IE; break; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -// -// Return interrupt flag list in Thumb instruction -// -static armFlagAffect getFlagAffectThumb( - armInstructionInfoP info, - aifSpec aif, - Uns32 instr -) { - armFlagAffect result = ARM_FAFF_NA; - - if((info->fact==ARM_FACT_IE) || (info->fact==ARM_FACT_ID)) { - switch(aif) { - case AIF_0: result = OP_AIF_0(instr); break; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - } - - return result; -} - -// -// Get the value of the U bit in the instruction -// -static Bool getUThumb(Uns32 instr, uSpec u) { - - Bool result = False; - - switch(u) { - case US_1: - result = True; - break; - case US_9: - result = OP_U_9(instr); - break; - case US_23: - result = OP_U_23(instr); - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -// -// Return indication of PSR bits specified by the instruction, if any -// -static armPSRBits getPSRBitsThumb( - armInstructionInfoP info, - maskSpec mask, - Uns32 instr -) { - armPSRBits result = ARM_PSRBITS_NA; - - switch(mask) { - case MSRMASK_NA: break; - case MSRMASK_10: result = OP_U_2_10(instr); break; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break; - } - - return result; -} - -// -// Return a modified immediate constant for the given immediate value -// If single is true then form a single precision value, -// otherwise form the high order 32 bits of a double precision value (low order 32 bits are always all 0's) -// -static armSdfpMItype modifiedImmediateVFPthumb(Uns32 imm, Bool single) { - - armSdfpMItype result; - - if (single) { - - // Set the sign bit to be a - result.u32.w0 = (imm & 0x80) ? 0x80000000 : 0; - - // Set the exponent sign to be Bbbbbb - where B = Not b - result.u32.w0 |= (imm & 0x40) ? 0x3e000000 : 0x40000000; - - // set the mantissa to cdefgh - result.u32.w0 |= (imm & 0x3f) << 19; - - // CLear the high order bits just to be safe - result.u32.w1 = 0; - - } else { - // Set the sign bit to be a - result.u64 = (imm & 0x80) ? 0x8000000000000000ULL : 0ULL; - - // Set the exponent sign to be Bbbbbbbbb - where B = Not b - result.u64 |= (imm & 0x40) ? 0x3fc0000000000000ULL : 0x4000000000000000ULL; - - // set the mantissa to cdefgh - result.u64 |= ((Uns64) (imm & 0x3f)) << 48; - - } - - return result; -} - -// -// Decode and return a SIMD/VFP modified immediate constant encoded within the ARM instruction -// -static armSdfpMItype getSdfpMIthumb( - Uns32 instr, - sdfpMISpec s, - armSDFPType dt -) { - - armSdfpMItype result; - - result.u64 = 0; - - switch (s) { - - case SDFP_MI_NA: - break; - case SDFP_MI_VFP_S: - VMI_ASSERT(dt == ARM_SDFPT_F32, "VFP Modified immediate constant type does not match dt"); - result = modifiedImmediateVFPthumb(OP_U_8_16_0(instr), True); - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -// -// Return the VFP scalar index encoded in the Thumb instruction -// -static Int8 getIndexThumb(Uns32 instr, indexSpec index) { - - Int8 result = 0; - - switch(index) { - case IDX_NA: - break; - case IDX_21: - result = OP_U_1_21(instr); - break; - case IDX_5: - result = OP_U_1_5(instr); - break; - case IDX_7: - result = OP_U_1_7(instr); - break; - case IDX_19: - result = OP_U_1_19(instr); - break; - default: - VMI_ABORT("%s: unimplemented case", FUNC_NAME); - break; - } - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// PUBLIC INTERFACE -//////////////////////////////////////////////////////////////////////////////// - -// -// Bitmasks for identification of 32-bit Thumb instructions -// -#define THUMB32_MASK 0xf800 -#define THUMB32_BL_H01 0xe800 -#define THUMB32_BL_H10 0xf000 -#define THUMB32_BL_H11 0xf800 - -// -// Return size in bytes of Thumb instruction at the passed address -// -Uns32 armGetThumbInstructionSize(armP arm, Uns32 thisPC) { - - Uns16 instr1 = vmicxtFetch2Byte((vmiProcessorP)arm, thisPC); - Uns16 hw1 = instr1 & THUMB32_MASK; - Bool isBL_H01 = (hw1==THUMB32_BL_H01); - Bool isBL_H10 = (hw1==THUMB32_BL_H10); - Bool isBL_H11 = (hw1==THUMB32_BL_H11); - - return (isBL_H01 || isBL_H10 || isBL_H11) ? 4 : 2; -} - -// -// Decode the Thumb instruction at the passed address. The 'info' structure is -// filled with details of the instruction. -// -void armDecodeThumb(armP arm, Uns32 thisPC, armInstructionInfoP info) { - - vmiProcessorP processor = (vmiProcessorP)arm; - Uns32 bytes = armGetThumbInstructionSize(arm, thisPC); - Uns32 instr = vmicxtFetch2Byte(processor, thisPC); - armThumbType type; - - // fetch instruction and decode it based on size - if(bytes==2) { - type = vmidDecode(getDecodeTableThumb16(), instr); - } else { - instr = (instr<<16) | vmicxtFetch2Byte(processor, thisPC+2); - type = vmidDecode(getDecodeTableThumb32(), instr); - } - - // save instruction - info->instruction = instr; - - // get instruction attributes based on type - opAttrsCP attrs = &attrsArray[type]; - - // get the equivalent main series type - info->type = attrs->type; - - // specify the name and format for the opcode - info->opcode = attrs->opcode; - info->format = attrs->format; - - // specify required architecture for the instruction - info->support = attrs->support; - info->isar = attrs->isar; - - // save instruction bytes - info->bytes = bytes; - - // get any flags set in the instruction - info->f = getSetFlagsThumb(arm, instr, attrs->f); - - // indicate whether the instruction is conditional - info->cond = getConditionThumb(arm, instr, attrs->cond); - - // get registers used by this instruction - info->r1 = getRegisterThumb(instr, attrs->r1); - info->r2 = getRegisterThumb(instr, attrs->r2); - info->r3 = getRegisterThumb(instr, attrs->r3); - info->r4 = getRegisterThumb(instr, attrs->r4); - - // get shiftop for the instruction - info->so = getShiftOpThumb(instr, attrs->ss); - - // get load/store size, sign extension, translate and exclusive access - // settings - info->sz = attrs->sz; - info->w = getWidthThumb(instr, attrs->w); - info->xs = attrs->xs; - info->tl = attrs->tl; - info->ea = attrs->ea; - - // does the opcode have a long load field? - info->ll = attrs->ll ? OP_LL(instr) : 0; - - // get U bit (must be valid *before* getConstantThumb which uses it) - info->u = getUThumb(instr, attrs->u); - - // get any constant value and constant rotate associated with the instruction - info->c = getConstantThumb( - arm, info, instr, attrs->cs, info->so, &info->crotate - ); - - // get any constant target address associated with the instruction - info->t = getTargetThumb(info, instr, attrs->ts); - - // get any coprocessor fields associated with the instruction - info->cpNum = attrs->cpNum ? OP_CPNUM(instr) : 0; - info->cpOp1 = getCpOp1Thumb(arm, info, instr, attrs->cpOp1); - info->cpOp2 = attrs->cpOp2 ? OP_CPOP2(instr) : 0; - - // get any _bits specification for MSR instructions - info->psrbits = getPSRBitsThumb(info, attrs->mask, instr); - - // get any register list and increment/decrement specification - info->rList = getRListThumb(instr, attrs->rList); - info->incDec = getIncDecThumb(info, arm, instr, attrs->incDec); - - // get post-indexed and writeback attributes for the instruction - info->pi = getPostIndexedThumb(instr, attrs->pi); - info->wb = info->pi || getWritebackThumb(instr, attrs->wb, info->r1, info->rList); - - // specify action on unaligned access - info->ua = attrs->ua67; - - // get flag and mode effect fields (CPS instruction) - info->ma = attrs->m ? OP_MA(instr) : 0; - info->fact = getFlagActionThumb(info, attrs->imod, instr); - info->faff = getFlagAffectThumb(info, attrs->aif, instr); - - // get if-then specification - info->it = attrs->it ? OP_IT(instr) : 0; - - // Get VFP specifications - info->index = getIndexThumb(instr, attrs->index); - info->nregs = getNRegsThumb(instr, attrs->nregs); - - // get any SIMD modified immediate constant value (64 bits long) - info->sdfpMI = getSdfpMIthumb (instr, attrs->sdfpMI, attrs->dt1); - - // get floating point type specification - info->dt1 = attrs->dt1; - info->dt2 = attrs->dt2; -} diff --git a/simulators/ovp/armmModel/armmDisassemble.c b/simulators/ovp/armmModel/armmDisassemble.c deleted file mode 100644 index e7144897..00000000 --- a/simulators/ovp/armmModel/armmDisassemble.c +++ /dev/null @@ -1,929 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// standard includes -#include -#include - -// VMI header files -#include "vmi/vmiCxt.h" -#include "vmi/vmiMessage.h" - -// model header files -#include "armDecode.h" -#include "armDisassemble.h" -#include "armDisassembleFormats.h" -#include "armFunctions.h" -#include "armStructure.h" -#include "armUtils.h" - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_DISASS" - -// -// This defines the minimum string width to use for the opcode -// -#define OP_WIDTH 7 - -// -// Condition names -// -static const char *condNames[] = { - "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", - "hi", "ls", "ge", "lt", "gt", "le", "" , "" -}; - -// -// Condition names in an IT block -// -static const char *condNamesIT[] = { - "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", - "hi", "ls", "ge", "lt", "gt", "le", "al", "al" -}; - -// -// Limitation names -// -static const char *limNames[] = { - "#0", "#1", "oshst", "osh", "#4", "#5", "nshst", "nsh", - "#8", "#9", "ishst", "ish", "#12", "#13", "st", "sy" -}; - -// -// Increment/decrement names -// -static const char *incDecNames[] = { - [ARM_ID_NA] = "", - [ARM_ID_IA] = "ia", - [ARM_ID_IB] = "ib", - [ARM_ID_DA] = "da", - [ARM_ID_DB] = "db", - [ARM_ID_IAI] = "", - [ARM_ID_IBI] = "", - [ARM_ID_DBI] = "", - [ARM_ID_DAI] = "" -}; - -// -// Flag action names -// -static const char *flagActionNames[] = { - [ARM_FACT_NA] = "", - [ARM_FACT_BAD] = "", - [ARM_FACT_IE] = "ie", - [ARM_FACT_ID] = "id" -}; - -// -// Size names -// -static const char *sizeNames[] = {"", "b", "h", "", "", "", "", "", "d"}; - -// -// Shift names -// -static const char *shiftNames[] = {"???", "lsl", "lsr", "asr", "ror", "rrx"}; - -// -// Names for armSDFPType values -// Note most not used in single precision VFP-Only M profile -// -static const char *ftypeNames[] = { - [ARM_SDFPT_NA] = "", // no floating point type - [ARM_SDFPT_8] = ".8", - [ARM_SDFPT_16] = ".16", - [ARM_SDFPT_32] = ".32", - [ARM_SDFPT_64] = ".64", - [ARM_SDFPT_F16] = ".f16", - [ARM_SDFPT_F32] = ".f32", - [ARM_SDFPT_F64] = ".f64", - [ARM_SDFPT_I8] = ".i8", - [ARM_SDFPT_I16] = ".i16", - [ARM_SDFPT_I32] = ".i32", - [ARM_SDFPT_I64] = ".i64", - [ARM_SDFPT_P8] = ".p8", - [ARM_SDFPT_S8] = ".s8", - [ARM_SDFPT_S16] = ".s16", - [ARM_SDFPT_S32] = ".s32", - [ARM_SDFPT_S64] = ".s64", - [ARM_SDFPT_U8] = ".u8", - [ARM_SDFPT_U16] = ".u16", - [ARM_SDFPT_U32] = ".u32", - [ARM_SDFPT_U64] = ".u64", -}; - -// -// Append the character to to the result -// -static void putChar(char **result, char ch) { - - // get the tail pointer - char *tail = *result; - - // do the append - *tail++ = ch; - - // add null terminator - *tail = 0; - - // update the tail pointer - *result = tail; -} - -// -// Append the string to to the result -// -static void putString(char **result, const char *string) { - - // get the tail pointer - char *tail = *result; - char ch; - - // do the append - while((ch=*string++)) { - *tail++ = ch; - } - - // add null terminator - *tail = 0; - - // update the tail pointer - *result = tail; -} - -// -// Append comma separator, unless previous character is space or comma (allows -// for omitted optional arguments) -// -static void putComma(char **result) { - - char *tail = *result; - - switch(tail[-1]) { - case ',': - case ' ': - break; - default: - putChar(result, ','); - break; - } -} - -// -// Append right bracket, overwriting any previous comma (allows for omitted -// optional arguments) -// -static void putRBracket(char **result) { - - char *tail = *result; - - switch(tail[-1]) { - case ',': - tail[-1] = ']'; - break; - default: - putChar(result, ']'); - break; - } -} - -// -// Emit hexadecimal argument using format 0x%x -// -static void put0x(char **result, Uns32 value) { - char tmp[32]; - sprintf(tmp, "0x%x", value); - putString(result, tmp); -} - -// -// Emit hexadecimal Uns64 argument using format 0x%x -// -static void put0xll(char **result, Uns64 value) { - char tmp[32]; - sprintf(tmp, "0x"FMT_640Nx, value); - putString(result, tmp); -} - -// -// Emit unsigned argument -// -static void putU(char **result, Uns32 value) { - char tmp[32]; - sprintf(tmp, "%u", value); - putString(result, tmp); -} - -// -// Emit floating point argument -// -static void putF(char **result, Flt64 value) { - char tmp[32]; - sprintf(tmp, "%g", value); - putString(result, tmp); -} - -// -// Emit signed argument -// -static void putD(char **result, Uns32 value) { - char tmp[32]; - sprintf(tmp, "%d", value); - putString(result, tmp); -} - -// -// Emit unsigned argument preceded with hash -// -static void putHashU(char **result, Uns32 value) { - putChar(result, '#'); - putU(result, value); -} - -// -// Emit constant 0 floating point argument preceded with hash -// -static void putHashF0(char **result) { - putString(result, "#0.0"); -} - -// -// Emit signed argument preceded with hash, unless optional and zero -// -static void putHashD(char **result, Uns32 value, Bool opt) { - if(!opt || value) { - putChar(result, '#'); - putD(result, value); - } -} - -// -// Emit minus sign if required -// -static void putMinus(char **result, Bool uBit) { - if(!uBit) { - putChar(result, '-'); - } -} - -// -// Emit instruction format if required -// -static void putInstruction(armP arm, armInstructionInfoP info, char **result) { - - char tmp[32]; - - // emit basic opcode string - sprintf(tmp, info->bytes==2 ? "%04x " : "%08x ", info->instruction); - putString(result, tmp); -} - -// -// Emit GPR argument -// -static void putGPR(armP arm, char **result, Uns32 r) { - putString(result, armGetGPRName(arm, r)); -} - -// -// Emit GPR argument, or flags if r15 and UAL mode -// -static void putGPROrFlagsIfR15(armP arm, char **result, Uns32 r) { - if(!arm->UAL || (r!=15)) { - putString(result, armGetGPRName(arm, r)); - } else { - putString(result, "APSR_nzcv"); - } -} - -// -// Emit singleword register argument -// -static void putSR(armP arm, char **result, Uns32 r) { - putChar(result, 's'); - putU(result, r); -} - -// -// Emit consecutive pair of singleword registers argument -// -static void putSSR(armP arm, char **result, Uns32 r) { - putChar(result, 's'); - putU(result, r); - putString(result, ",s"); - putU(result, r+1); -} - -// -// Emit doubleword register argument -// -static void putDR(armP arm, char **result, Uns32 r) { - putChar(result, 'd'); - putU(result, r); -} - -// -// Emit scalar argument -// -static void putScalar(armP arm, char **result, Uns32 d, Uns32 index) { - putChar(result, 'd'); - putU(result, d); - putChar(result, '['); - putU(result, index); - putChar(result, ']'); -} - -// -// Emit CPR argument -// -static void putCPR(armP arm, char **result, Uns32 r) { - putString(result, armGetCPRName(arm, r)); -} - -// -// Emit fpscr argument (M-profile only supports "fpscr" on vmrs/vmsr) -// -static void putFPSCR(armP arm, char **result) { - putString(result, "fpscr"); -} - -// -// Emit jump target -// -static void putTarget(char **result, Uns32 value) { - char tmp[32]; - sprintf(tmp, "%x", value); - putString(result, tmp); -} - -// -// Emit shiftop argument -// -static void putShift(char **result, armShiftOp so) { - putString(result, shiftNames[so]); -} - -// -// Emit constant shift if non-zero -// -static void putShiftC(char **result, armShiftOp so, Uns32 value) { - if(value) { - putShift(result, so); - putChar(result, ' '); - putHashD(result, value, False); - } -} - -// -// Emit constant shift equivalent to size if non-zero -// -static void putSizeShift(char **result, Uns32 sz) { - - Uns32 shift = 0; - - while(sz>1) { - sz >>= 1; - shift++; - } - - putShiftC(result, ARM_SO_LSL, shift); -} - -// -// Emit writeback argument -// -static void putWB(char **result, Bool pi, Bool wb) { - if(wb && !pi) { - putChar(result, '!'); - } -} - -// -// Emit register list argument -// -static void putRList(armP arm, char **result, Uns32 rList) { - - Uns32 r; - Uns32 mask; - Bool first = True; - - putChar(result, '{'); - - for(r=0, mask=0x0001; r<16; r++, mask<<=1) { - if(rList&mask) { - if(!first) { - putChar(result, ','); - } - putGPR(arm, result, r); - first = False; - } - } - - putChar(result, '}'); -} - -// -// Return string for _ of MSR instruction defined -// by the instruction's mask field -// -static char *msrBits(armPSRBits bits) { - - char *s; - - switch (bits) { - case ARM_PSRBITS_GE: s = "_g"; break; - // Support for the GE bits was added by Arm in Q3 2010 so now - // this should be s = "_nzcvq", but toolchains do not seem to support it yet - // so continue using the (deprecated) empty string for now - case ARM_PSRBITS_FLAGS: s = NULL; break; - case ARM_PSRBITS_ALL: s = "_nzcvqg"; break; - default: s = NULL; break; - } - - return s; -} - -// -// Emit special register argument -// -static void putSpecialReg(char **result, armSysRegId SYSm, armPSRBits bits) { - - const char *regName; - const char *bitsName = NULL; - - switch(SYSm) { - case ASRID_APSR: regName = "APSR"; bitsName = msrBits(bits); break; - case ASRID_IAPSR: regName = "IAPSR"; bitsName = msrBits(bits); break; - case ASRID_EAPSR: regName = "EAPSR"; bitsName = msrBits(bits); break; - case ASRID_XPSR: regName = "XPSR"; bitsName = msrBits(bits); break; - case ASRID_IPSR: regName = "IPSR"; break; - case ASRID_EPSR: regName = "EPSR"; break; - case ASRID_IEPSR: regName = "IEPSR"; break; - case ASRID_MSP: regName = "MSP"; break; - case ASRID_PSP: regName = "PSP"; break; - case ASRID_PRIMASK: regName = "PRIMASK"; break; - case ASRID_BASEPRI: regName = "BASEPRI"; break; - case ASRID_BASEPRI_MAX: regName = "BASEPRI_MAX"; break; - case ASRID_FAULTMASK: regName = "FAULTMASK"; break; - case ASRID_CONTROL: regName = "CONTROL"; break; - default: regName = "RSVD"; break; - } - - putString(result, regName); - if (bitsName != NULL) putString(result, bitsName); -} - -// -// Emit flags argument (CPS instruction) -// -static void putFlags(char **result, armFlagAffect faff) { - if(faff & ARM_FAFF_A) {putChar(result, 'a');} - if(faff & ARM_FAFF_I) {putChar(result, 'i');} - if(faff & ARM_FAFF_F) {putChar(result, 'f');} -} - -// -// Emit optional mode argument (CPS instruction) -// -static void putOptMode(char **result, Bool ma, Uns32 c) { - if(ma) {putHashU(result, c);} -} - -// -// Emit limitation (DMB, DSB and ISB instructions) -// -static void putLim(char **result, Uns32 lim) { - putString(result, limNames[lim]); -} - -// -// Emit true/else condition list for IT block -// -static void putIT(char **result, Uns32 it) { - - Bool negate = (it&0x10) ? False : True; - - while(it & 0x7) { - Bool select = (it & 0x8) ? True : False; - putChar(result, (select ^ negate) ? 't' : 'e'); - it <<= 1; - } -} - -// -// Emit a single register in a register list -// May be a scalar which may or may not have a valid index -// -static void putRListReg(char **result, Uns32 rn, char regType, Bool scalar, Int32 index) { - - putChar(result, regType); - putU(result, rn); - if (scalar) { - putChar(result, '['); - if (index >= 0) putU(result, (Uns32) index); - putChar(result, ']'); - } -} - -// -// Emit SIMD/VFP type register list argument -// -static void putSdfpRList( - char **result, - Uns32 nRegs, - Uns32 incr, - Uns32 rn, - char regType, - Bool scalar, - Int32 index, - Bool forceList -) { - - putChar(result, '{'); - putRListReg(result, rn, regType, scalar, index); - - if (incr > 1 || forceList) { - - // when there is an incr (or when forced) use a list of regs rx, ry,...rz - int i; - - // If forcing a list make sure incr is valid - if (incr == 0) incr = 1; - - for (i = 1; i < nRegs; i++) { - putChar(result, ','); - putRListReg(result, rn+(incr*i), regType, scalar, index); - } - - } else { - - // When there is no incr, disassembler uses rx-rz notation for multiple registers - if (nRegs > 1) { - putChar(result, '-'); - putRListReg(result, rn+nRegs-1, regType, scalar, index); - } - - } - - putChar(result, '}'); -} - -// -// Emit a SIMD/VFP Modified Immediate constant value -// -static void putSdfpMI(char **result, armSdfpMItype mi, armSDFPType ftype) -{ - putChar(result, '#'); - - switch (ftype) { - - case ARM_SDFPT_I8: - putD(result, mi.u8.b0); - break; - case ARM_SDFPT_I16: - putD(result, mi.u16.h0); - break; - case ARM_SDFPT_I32: - putD(result, mi.u32.w0); - break; - case ARM_SDFPT_I64: - put0xll(result, mi.u64); - break; - case ARM_SDFPT_F32: - putF(result, mi.f32); - break; - case ARM_SDFPT_F64: - putF(result, mi.f64); - break; - default: - // Only above values for dt1 are supported for instructions with modified immediate constants - VMI_ABORT("Unsupported ftype %d withSIMD/VFP modified immediate constant", ftype); - - } -} - -// -// Generate instruction disassembly using the format string -// -static void disassembleFormat( - armP arm, - armInstructionInfoP info, - char **result, - const char *format -) { - const char *opcode = info->opcode; - - // in UAL mode, some instances of MOV instruction get reclassed as shift - // pseudo-ops - if(!arm->UAL) { - // no action - } else if((info->type==ARM_IT_MOV_RM_SHFT_IMM) && info->c) { - opcode = shiftNames[info->so]; - format = FMT_R1_R2_SIMM; - } else if(info->type==ARM_IT_MOV_RM_SHFT_RS) { - opcode = shiftNames[info->so]; - format = FMT_R1_R2_R3; - } else if(info->type==ARM_IT_MOV_RM_RRX) { - opcode = shiftNames[info->so]; - format = FMT_R1_R2; - } - - // generate instruction pattern - putInstruction(arm, info, result); - - // get offset at opcode start - const char *opcodeStart = *result; - - // generate opcode text - putString(result, opcode); - - if(arm->UAL) { - // disassemble using UAL syntax - if(info->xs) putChar(result, 's'); - if(info->ea) putString(result, "ex"); - putString(result, sizeNames[info->sz]); - if(info->f==ARM_SF_V) putChar(result, 's'); - putString(result, incDecNames[info->incDec]); - putString(result, condNames[info->cond]); - putString(result, flagActionNames[info->fact]); - if(info->tl) putChar(result, 't'); - if(info->ll) putChar(result, 'l'); - if(info->it) putIT(result, info->it); - putString(result, ftypeNames[info->dt1]); - putString(result, ftypeNames[info->dt2]); - } else { - // disassemble using pre-UAL syntax - putString(result, condNames[info->cond]); - putString(result, incDecNames[info->incDec]); - putString(result, flagActionNames[info->fact]); - if(info->xs) putChar(result, 's'); - if(info->ea) putString(result, "ex"); - putString(result, sizeNames[info->sz]); - if(info->tl) putChar(result, 't'); - if(info->ll) putChar(result, 'l'); - if(info->f==ARM_SF_V) putChar(result, 's'); - if(info->it) putIT(result, info->it); - putString(result, ftypeNames[info->dt1]); - putString(result, ftypeNames[info->dt2]); - } - - if(*format) { - - // calculate length of opcode text - const char *opcodeEnd = *result; - Uns32 len = opcodeEnd-opcodeStart; - char ch; - - // pad to minimum width - for(; lenr1); - break; - case EMIT_R2: - putGPR(arm, result, info->r2); - break; - case EMIT_R3: - putGPR(arm, result, info->r3); - break; - case EMIT_R4: - putGPR(arm, result, info->r4); - break; - case EMIT_S1: - putSR(arm, result, info->r1); - break; - case EMIT_S2: - putSR(arm, result, info->r2); - break; - case EMIT_S3: - putSR(arm, result, info->r3); - break; - case EMIT_D1: - putDR(arm, result, info->r1); - break; - case EMIT_D2: - putDR(arm, result, info->r2); - break; - case EMIT_D3: - putDR(arm, result, info->r3); - break; - case EMIT_Z1: - putScalar(arm, result, info->r1, info->index); - break; - case EMIT_Z2: - putScalar(arm, result, info->r2, info->index); - break; - case EMIT_SS1: - putSSR(arm, result, info->r1); - break; - case EMIT_SS3: - putSSR(arm, result, info->r3); - break; - case EMIT_CU: - putHashU(result, info->c); - break; - case EMIT_CS: - putHashD(result, info->c, opt); - break; - case EMIT_CX: - put0x(result, info->c); - break; - case EMIT_T: - putTarget(result, info->t); - break; - case EMIT_SHIFT: - putShift(result, info->so); - break; - case EMIT_SHIFT_C: - putShiftC(result, info->so, info->c); - break; - case EMIT_CPNUM: - putU(result, info->cpNum); - break; - case EMIT_COP1: - putU(result, info->cpOp1); - break; - case EMIT_COP2: - putU(result, info->cpOp2); - break; - case EMIT_CR1: - putCPR(arm, result, info->r1); - break; - case EMIT_CR2: - putCPR(arm, result, info->r2); - break; - case EMIT_CR3: - putCPR(arm, result, info->r3); - break; - case EMIT_OPT: - putU(result, info->c); - break; - case EMIT_WB: - putWB(result, info->pi, info->wb); - break; - case EMIT_RLIST: - putRList(arm, result, info->rList); - break; - case EMIT_U: - putMinus(result, info->u); - break; - case EMIT_SR: - putSpecialReg(result, info->c, info->psrbits); - break; - case EMIT_FLAGS: - putFlags(result, info->faff); - break; - case EMIT_OPT_MODE: - putOptMode(result, info->ma, info->c); - break; - case EMIT_LIM: - putLim(result, info->c); - break; - case EMIT_WIDTH: - putHashD(result, info->w, False); - break; - case EMIT_ITC: - putString(result, condNamesIT[info->it>>4]); - break; - case EMIT_SZSHIFT: - putSizeShift(result, info->sz); - break; - case EMIT_R1F: - putGPROrFlagsIfR15(arm, result, info->r1); - break; - case EMIT_FPSCR: - putFPSCR(arm, result); - break; - case EMIT_C0F: - putHashF0(result); - break; - case EMIT_SIMD_RL: - putSdfpRList(result, info->nregs, 0, info->r2, 'd', False, 0, False); - break; - case EMIT_SDFP_MI: - putSdfpMI(result, info->sdfpMI, info->dt1); - break; - case EMIT_VFP_RL: - putSdfpRList(result, info->nregs, 0, info->r2, 's', False, 0, False); - break; - case '1': - if(!info->pi) format++; - break; - case '2': - if(info->pi) format++; - break; - case ',': - putComma(result); - break; - case ']': - putRBracket(result); - break; - case '*': - nextOpt = True; - break; - default: - putChar(result, ch); - break; - } - } - } - - // strip trailing whitespace and commas - char *tail = (*result)-1; - while((*tail == ' ') || (*tail == ',')) { - *tail-- = 0; - } -} - -// -// ARM disassembler, decoded instruction interface -// -const char *armDisassembleInfo(armP arm, armInstructionInfoP info) { - - // static buffer to hold disassembly result - static char result[256]; - const char *format = info->format; - char *tail = result; - - // disassemble using the format for the type - if(format) { - disassembleFormat(arm, info, &tail, format); - } else if(info->bytes==2) { - sprintf(result, "0x%04x", info->instruction); - } else { - sprintf(result, "0x%08x", info->instruction); - } - - // return the result - return result; -} - -// -// ARM disassembler, VMI interface -// -VMI_DISASSEMBLE_FN(armDisassemble) { - - // static buffer to hold disassembly result - armP arm = (armP)processor; - armInstructionInfo info; - - // get instruction and instruction type - arm->itStateMT = arm->itStateRT; - armDecode(arm, thisPC, &info); - - // return disassembled instruction - return armDisassembleInfo(arm, &info); -} - - diff --git a/simulators/ovp/armmModel/armmDoc.c b/simulators/ovp/armmModel/armmDoc.c deleted file mode 100644 index 2701ac52..00000000 --- a/simulators/ovp/armmModel/armmDoc.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiAttrs.h" -#include "vmi/vmiModelInfo.h" -#include "vmi/vmiDoc.h" - -#include "armmDoc.h" -#include "armmParameters.h" -#include "armStructure.h" -#include "armConfig.h" - -void armmDoc(vmiProcessorP processor, armParamValuesP parameters) { - vmiDocNodeP root = vmidocAddSection(0, "Root"); - vmiDocNodeP desc = vmidocAddSection(root, "Description"); - vmidocAddText(desc, "ARMM Processor Model"); - - vmiDocNodeP lic = vmidocAddSection(root, "Licensing"); - vmidocAddText(lic, "Imperas Modified Apache 2.0 Open Source License"); - - vmiDocNodeP lim = vmidocAddSection(root, "Limitations"); - vmidocAddText(lim, "Security Extensions are not yet implemented."); - vmidocAddText(lim, "Performance Monitors are not implemented."); - - vmiDocNodeP verif = vmidocAddSection(root, "Verification"); - vmidocAddText(verif, "Models have been validated correct by Imperas " - "running through extensive unit and full operating system tests " - "and validated in some cases against hardware"); - - armP arm = (armP) processor; - - vmiDocNodeP features = vmidocAddSection(root, "Features"); - - if (MPU_PRESENT(arm)) { - vmidocAddText(features, "MPU is implemented."); - } - - if (ARM_SUPPORT(arm->configInfo.arch, ARM_VT)) { - vmidocAddText(features, "Thumb instructions are supported."); - } - if (ARM_SUPPORT(arm->configInfo.arch, ARM_VT2)) { - vmidocAddText(features, "Thumb-2 instructions are supported."); - } - if (ARM_SUPPORT(arm->configInfo.arch, ARM_J)) { - vmidocAddText(features, "Jazelle trap is implemented."); - } - - vmidocProcessor(processor, root); -} diff --git a/simulators/ovp/armmModel/armmDoc.h b/simulators/ovp/armmModel/armmDoc.h deleted file mode 100644 index fc70a94f..00000000 --- a/simulators/ovp/armmModel/armmDoc.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARMM_DOC_H -#define ARMM_DOC_H - -#include "vmi/vmiTyperefs.h" -#include "armmParameters.h" - -void armmDoc(vmiProcessorP processor, armParamValuesP parameters); - -#endif diff --git a/simulators/ovp/armmModel/armmEmit.c b/simulators/ovp/armmModel/armmEmit.c deleted file mode 100644 index 6cab46ca..00000000 --- a/simulators/ovp/armmModel/armmEmit.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiAttrs.h" -#include "vmi/vmiMt.h" -#include "vmi/vmiRt.h" -#include "vmi/vmiMessage.h" - -// model header files -#include "armDecode.h" -#include "armEmit.h" -#include "armExceptions.h" -#include "armFunctions.h" -#include "armMode.h" -#include "armMorph.h" -#include "armStructure.h" -#include "armRegisters.h" -#include "armUtils.h" - - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_EMIT" - - -//////////////////////////////////////////////////////////////////////////////// -// SPECIAL HANDLING FOR PC UPDATES -//////////////////////////////////////////////////////////////////////////////// - -// -// Is the passed register the link register? -// -inline static Bool isLinkReg(vmiReg ra) { - return VMI_REG_EQUAL(ra, ARM_LR); -} - -// -// Invalidate derived flags dependent on ZF -// -inline static void invalidateZF(armMorphStateP state) { - state->arm->validLE = False; - state->arm->validHI = False; -} - -// -// Invalidate derived flags dependent on NF -// -inline static void invalidateNF(armMorphStateP state) { - state->arm->validLE = False; - state->arm->validLT = False; -} - -// -// Invalidate derived flags dependent on CF -// -inline static void invalidateCF(armMorphStateP state) { - state->arm->validHI = False; -} - -// -// Invalidate derived flags dependent on VF -// -inline static void invalidateVF(armMorphStateP state) { - state->arm->validLE = False; - state->arm->validLT = False; -} - -// -// Invalidate any derived flags if a flag register is being assigned -// -static void invalidateDerivedReg(armMorphStateP state, vmiReg rd) { - if(VMI_REG_EQUAL(rd, ARM_ZF)) { - invalidateZF(state); - } else if(VMI_REG_EQUAL(rd, ARM_NF)) { - invalidateNF(state); - } else if(VMI_REG_EQUAL(rd, ARM_CF)) { - invalidateCF(state); - } else if(VMI_REG_EQUAL(rd, ARM_VF)) { - invalidateVF(state); - } -} - -// -// Invalidate derived flags for all flags assigned in the flags structure -// -static void invalidateDerivedFlags(armMorphStateP state, vmiFlagsCP flags) { - if(flags) { - invalidateDerivedReg(state, flags->f[vmi_CF]); - invalidateDerivedReg(state, flags->f[vmi_ZF]); - invalidateDerivedReg(state, flags->f[vmi_SF]); - invalidateDerivedReg(state, flags->f[vmi_OF]); - } -} - -// -// Called when register is assigned a variable value -// -static void setVariable(armMorphStateP state, vmiReg rd, Bool isReturn) { - - armP arm = state->arm; - - // assignment to a flag should invalidate any derived flags - invalidateDerivedReg(state, rd); - - // possibly a special jump if PC is being assigned - if(VMI_REG_EQUAL(rd, ARM_PC)) { - - Uns32 version = ARM_INSTRUCTION_VERSION(arm->configInfo.arch); - Bool interwork = False; - - switch(state->attrs->interwork) { - - case ARM_IW_L4: - // always an interworking instruction - interwork = True; - break; - - case ARM_IW_ARM_V7: - // an interworking instruction if ARMv7 or above and an ARM - // instruction that does not set flags (not Thumb) - interwork = ((version>=7) && !IN_THUMB_MODE(arm) && !state->info.f); - break; - - default: - // never an interworking instruction (or an explicit - // interworking instruction) - break; - } - - state->pcSet = isReturn ? ASPC_R15_RET : ASPC_R15; - state->setMode = interwork; - } -} - -// -// Called to mask result value if required -// -static void maskResult(vmiReg rd) { - - if(VMI_REG_EQUAL(rd, ARM_SP)) { - - // sp_main is 4-byte aligned - vmimtBinopRC(ARM_GPR_BITS, vmi_AND, rd, ~3, 0); - - } else if(VMI_REG_EQUAL(rd, ARM_BANK_SP)) { - - // sp_process is 4-byte aligned - vmimtBinopRC(ARM_GPR_BITS, vmi_AND, rd, ~3, 0); - } -} - -// -// Called when register is assigned a constant value -// -static Bool setConstant(armMorphStateP state, vmiReg rd, Uns32 c) { - - // assignment to a flag should invalidate any derived flags - invalidateDerivedReg(state, rd); - - // special jump if PC is being assigned - if(!VMI_REG_EQUAL(rd, ARM_PC)) { - return False; - } else { - state->pcSet = ASPC_IMM; - state->pcImmediate = c; - return True; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// MODE SWITCH -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code to switch state between normal and Thumb mode -// -void armEmitInterwork(armMorphStateP state) { - - // toggle Thumb bit in PSR - vmimtBinopRC(ARM_GPR_BITS, vmi_XOR, ARM_PSR, PSR_THUMB, 0); - - // make call to switch to ARM mode (will immediately take exception) - vmimtArgProcessor(); - vmimtCall((vmiCallFn)armSwitchMode); -} - - -//////////////////////////////////////////////////////////////////////////////// -// INTEGER OPCODES -//////////////////////////////////////////////////////////////////////////////// - -// -// Get delta applied to the current PC to get the value returned when PC is a -// source argument -// -inline static Uns32 getPCDelta(armMorphStateP state) { - return (IN_THUMB_MODE(state->arm) ? 4 : 8); -} - -// -// rd = simPC (true) -// -void armEmitGetTruePC(armMorphStateP state, vmiReg rd) { - vmimtMoveRSimPC(ARM_GPR_BITS, rd); -} - -// -// r15 = simPC (according to ARM pipeline) -// -void armEmitGetPC(armMorphStateP state) { - if(!state->pcFetched) { - state->pcFetched = True; - vmimtMoveRSimPC(ARM_GPR_BITS, ARM_PC); - vmimtBinopRC(ARM_GPR_BITS, vmi_ADD, ARM_PC, getPCDelta(state), 0); - } -} - -// -// rd = c -// -void armEmitMoveRC( - armMorphStateP state, - Uns32 bits, - vmiReg rd, - Uns64 c -) { - if(!setConstant(state, rd, c)) { - vmimtMoveRC(bits, rd, c); - } -} - -// -// rd = ra -// -void armEmitMoveRR( - armMorphStateP state, - Uns32 bits, - vmiReg rd, - vmiReg ra -) { - setVariable(state, rd, isLinkReg(ra)); - vmimtMoveRR(bits, rd, ra); - maskResult(rd); -} - -// -// rd = ra -// -void armEmitMoveExtendRR( - armMorphStateP state, - Uns32 destBits, - vmiReg rd, - Uns32 srcBits, - vmiReg ra, - Bool signExtend -) { - setVariable(state, rd, False); - vmimtMoveExtendRR(destBits, rd, srcBits, ra, signExtend); - maskResult(rd); -} - -// -// rd = (flag==select1) ? c1 : c2 -// -void armEmitCondMoveRCC( - armMorphStateP state, - Uns32 bits, - vmiReg flag, - Bool select1, - vmiReg rd, - Uns64 c1, - Uns64 c2 -) { - setVariable(state, rd, False); - vmimtCondMoveRCC(bits, flag, select1, rd, c1, c2); - maskResult(rd); -} - -// -// rd = ra -// -void armEmitUnopRR( - armMorphStateP state, - Uns32 bits, - vmiUnop op, - vmiReg rd, - vmiReg ra, - vmiFlagsCP flags -) { - invalidateDerivedFlags(state, flags); - setVariable(state, rd, (op==vmi_MOV) && isLinkReg(ra)); - vmimtUnopRR(bits, op, rd, ra, flags); - maskResult(rd); -} - -// -// rd = c -// -void armEmitUnopRC( - armMorphStateP state, - Uns32 bits, - vmiUnop op, - vmiReg rd, - Uns64 c, - vmiFlagsCP flags -) { - invalidateDerivedFlags(state, flags); - - // convert constant so that value can be moved directly - if(op==vmi_MOV) { - // no action - } else if(op==vmi_NOT) { - op = vmi_MOV; - c = ~c; - } else { - VMI_ABORT("unexpected unary opcode %u", op); - } - - // operation is only required if the target is not the program counter or - // if flags are needed - if(!setConstant(state, rd, c) || flags) { - vmimtUnopRC(bits, op, rd, c, flags); - maskResult(rd); - } -} - -// -// rd = rd ra -// -void armEmitBinopRR( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - vmiReg ra, - vmiFlagsCP flags -) { - invalidateDerivedFlags(state, flags); - setVariable(state, rd, False); - vmimtBinopRR(bits, op, rd, ra, flags); - maskResult(rd); -} - -// -// rd = rd c -// -void armEmitBinopRC( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - Uns64 c, - vmiFlagsCP flags -) { - invalidateDerivedFlags(state, flags); - setVariable(state, rd, False); - vmimtBinopRC(bits, op, rd, c, flags); - maskResult(rd); -} - -// -// rd = ra rb -// -void armEmitBinopRRR( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - vmiReg ra, - vmiReg rb, - vmiFlagsCP flags -) { - invalidateDerivedFlags(state, flags); - setVariable(state, rd, False); - vmimtBinopRRR(bits, op, rd, ra, rb, flags); - maskResult(rd); -} - -// -// rd = ra c -// -void armEmitBinopRRC( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - vmiReg ra, - Uns64 c, - vmiFlagsCP flags -) { - invalidateDerivedFlags(state, flags); - setVariable(state, rd, False); - vmimtBinopRRC(bits, op, rd, ra, c, flags); - maskResult(rd); -} - -// -// Generate shift mask prefix (sets mask to 255) -// -void armEmitSetShiftMask(void) { - vmimtSetShiftMask(255); -} - -// -// rdh:rdl = ra*rb -// -void armEmitMulopRRR( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rdH, - vmiReg rdL, - vmiReg ra, - vmiReg rb, - vmiFlagsCP flags -) { - invalidateDerivedFlags(state, flags); - setVariable(state, rdL, False); - setVariable(state, rdH, False); - vmimtMulopRRR(bits, op, rdH, rdL, ra, rb, flags); - maskResult(rdH); - maskResult(rdL); -} -//////////////////////////////////////////////////////////////////////////////// -// FLOATING POINT OPCODES -//////////////////////////////////////////////////////////////////////////////// - -// -// Perform actions after a floating point operation -// -static void endFPOperation(armMorphStateP state, Bool setSticky) { - - if(setSticky) { - // merge sticky flags - vmimtBinopRR(8, vmi_OR, ARM_FP_STICKY, ARM_FP_FLAGS, 0); - } -} - -// -// fd = fa fb fc -// -void armEmitFTernopSimdRRRR( - armMorphStateP state, - vmiFType type, - Uns32 num, - vmiFTernop op, - vmiReg fd, - vmiReg fa, - vmiReg fb, - vmiReg fc, - Bool roundInt -) { - - // do the ternop - vmimtFTernopSimdRRRR(type, num, op, fd, fa, fb, fc, ARM_FP_FLAGS, roundInt); - - // do epilogue actions - endFPOperation(state, True); -} - - -// -// fd = fa fb -// -void armEmitFBinopSimdRRR( - armMorphStateP state, - vmiFType type, - Uns32 num, - vmiFBinop op, - vmiReg fd, - vmiReg fa, - vmiReg fb -) { - - // do the binop - vmimtFBinopSimdRRR(type, num, op, fd, fa, fb, ARM_FP_FLAGS); - - // do epilogue actions - endFPOperation(state, True); -} - -// -// fd = fa -// -void armEmitFUnopSimdRR( - armMorphStateP state, - vmiFType type, - Uns32 num, - vmiFUnop op, - vmiReg fd, - vmiReg fa -) { - - // do the unop - vmimtFUnopSimdRR(type, num, op, fd, fa, ARM_FP_FLAGS); - - // do epilogue actions - endFPOperation(state, True); -} - -// -// fd = fa -// -void armEmitFConvertRR( - armMorphStateP state, - vmiFType destType, - vmiReg fd, - vmiFType srcType, - vmiReg fa, - vmiFPRC round -) { - // conversions from integer values to longer values (integer or floating - // point) never produce exceptions or require rounding - Bool srcIsFP = !VMI_FTYPE_IS_INT(srcType); - Uns32 srcBits = VMI_FTYPE_BITS(srcType); - Uns32 destBits = VMI_FTYPE_BITS(destType); - Bool exceptOrRound = (srcIsFP || (srcBits>=destBits)); - - // do the conversion - vmimtFConvertRR(destType, fd, srcType, fa, round, ARM_FP_FLAGS); - - // do epilogue actions if exceptions were possible - if(exceptOrRound) { - endFPOperation(state, True); - } -} - -// -// compare fa to fb, setting relation and flags -// -void armEmitFCompareRR( - armMorphStateP state, - vmiFType type, - vmiReg relation, - vmiReg fa, - vmiReg fb, - Bool allowQNaN, - Bool setSticky -) { - - // do the compare - vmimtFCompareRR(type, relation, fa, fb, ARM_FP_FLAGS, allowQNaN); - - // do epilogue actions - endFPOperation(state, setSticky); -} - - -//////////////////////////////////////////////////////////////////////////////// -// LOAD AND STORE OPCODES -//////////////////////////////////////////////////////////////////////////////// - -// -// Return processor endianness (and add blockMask check to validate it if -// required) -// -static memEndian getEndian(armMorphStateP state, Uns32 bits) { - - armP arm = state->arm; - - // validate endianness for memory operations wider than a byte - if(arm->checkEndian && (bits>8)) { - vmimtValidateBlockMask(ARM_BM_BIG_ENDIAN); - } - - // return current endianness - return armGetEndian((vmiProcessorP)arm, False); -} - -// -// Indicate whether instruction requires alignment checking (and add blockMask -// check to validate it if required) -// -static Bool getAlign(armMorphStateP state, Uns32 bits) { - - armP arm = state->arm; - - // validate alignment checking for memory operations wider than a byte - if(arm->checkUnaligned && (bits>8)) { - vmimtValidateBlockMask(ARM_BM_UNALIGNED); - } - - // alignment checking required if ua is not ARM_UA_UNALIGNED - return !(DO_UNALIGNED(arm) && (state->info.ua==ARM_UA_UNALIGNED)); -} - -// -// mem[ra+offset] = rb (when ra!=VMI_NOREG) -// mem[offset] = rb (when ra==VMI_NOREG) -// -void armEmitStoreRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg ra, - vmiReg rb -) { - memEndian endian = getEndian(state, bits); - Bool align = getAlign(state, bits); - - // emit single store - vmimtStoreRRO(bits, offset, ra, rb, endian, align); -} - -// -// mem[ra+offset] = rbH:rbL (when ra!=VMI_NOREG) -// mem[offset] = rbH:rbL (when ra==VMI_NOREG) -// -void armEmitStoreRRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg ra, - vmiReg rbL, - vmiReg rbH -) { - Uns32 regBits = ARM_GPR_BITS; - armP arm = state->arm; - memEndian endian = getEndian(state, bits); - Bool align = getAlign(state, bits); - - // generate exception for misaligned or inaccessible address if required - if(!arm->configInfo.align64as32) { - vmimtTryStoreRC(bits, offset, ra, align); - } - - // emit two word stores - vmimtStoreRRO(regBits, offset, ra, rbL, endian, align); - vmimtStoreRRO(regBits, offset+4, ra, rbH, endian, align); -} - -// -// rd = mem[ra+offset] (when ra!=VMI_NOREG) -// rd = mem[offset] (when ra==VMI_NOREG) -// -void armEmitLoadRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg rd, - vmiReg ra, - Bool signExtend, - Bool isReturn -) { - Uns32 regBits = ARM_GPR_BITS; - memEndian endian = getEndian(state, bits); - Bool align = getAlign(state, bits); - - // emit single load - vmimtLoadRRO(regBits, bits, offset, rd, ra, endian, signExtend, align); - setVariable(state, rd, isReturn); - maskResult(rd); -} - -// -// rdH:rdL = mem[ra+offset] (when ra!=VMI_NOREG) -// rdH:rdL = mem[offset] (when ra==VMI_NOREG) -// -void armEmitLoadRRRO( - armMorphStateP state, - Uns32 bits, - Uns32 offset, - vmiReg rdL, - vmiReg rdH, - vmiReg ra, - vmiReg rt, - Bool signExtend, - Bool isReturn -) { - Uns32 regBits = ARM_GPR_BITS; - armP arm = state->arm; - memEndian endian = getEndian(state, bits); - Bool align = getAlign(state, bits); - - // generate exception for misaligned or inaccessible address if required - if(!arm->configInfo.align64as32) { - vmimtTryLoadRC(bits, offset, ra, align); - } - - // emit two word loads (the first into a temporary in case the second fails) - vmimtLoadRRO(regBits, regBits, offset, rt, ra, endian, False, align); - vmimtLoadRRO(regBits, regBits, offset+4, rdH, ra, endian, False, align); - vmimtMoveRR(regBits, rdL, rt); - setVariable(state, rdL, isReturn); - setVariable(state, rdH, isReturn); -} - -// -// trystore mem[ra+offset] (when ra!=VMI_NOREG) -// trystore mem[offset] (when ra==VMI_NOREG) -// -void armEmitTryStoreRC( - armMorphStateP state, - Uns32 bits, - Addr offset, - vmiReg ra -) { - vmimtTryStoreRC(bits, offset, ra, getAlign(state, bits)); -} - - -//////////////////////////////////////////////////////////////////////////////// -// COMPARE OPERATIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// flag = ra rb -// -void armEmitCompareRR( - armMorphStateP state, - Uns32 bits, - vmiCondition cond, - vmiReg ra, - vmiReg rb, - vmiReg flag -) { - vmimtCompareRR(bits, cond, ra, rb, flag); -} - -// -// flag = ra c -// -void armEmitCompareRC( - armMorphStateP state, - Uns32 bits, - vmiCondition cond, - vmiReg ra, - Uns64 c, - vmiReg flag -) { - vmimtCompareRC(bits, cond, ra, c, flag); -} - - -//////////////////////////////////////////////////////////////////////////////// -// INTER-INSTRUCTION CONDITIONAL AND UNCONDITIONAL JUMPS -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code to clear ITSTATE if required -// -static void emitClearITState(armMorphStateP state) { - if(state->arm->itStateMT) { - armEmitMoveRC(state, 8, ARM_IT_STATE, 0); - } -} - -// -// Set address mask to mask off the bottom bit of the target address -// -static void emitAddressMask(void) { - vmimtSetAddressMask(~1); -} - -// -// Perform an unconditional direct jump. -// -void armEmitUncondJump( - armMorphStateP state, - armJumpInfoP ji -) { - emitAddressMask(); - emitClearITState(state); - vmimtUncondJump( - ji->linkPC, - state->info.t, - ji->linkReg, - ji->hint - ); -} - -// -// Perform an unconditional indirect jump. -// -void armEmitUncondJumpReg( - armMorphStateP state, - armJumpInfoP ji, - vmiReg toReg -) { - emitAddressMask(); - emitClearITState(state); - vmimtUncondJumpReg( - ji->linkPC, - toReg, - ji->linkReg, - ji->hint - ); -} - -// -// Perform a conditional direct jump if the condition flag is non-zero -// (jumpIfTrue) or zero (not jumpIfTrue). -// -void armEmitCondJump( - armMorphStateP state, - armJumpInfoP ji, - vmiReg flag, - Bool jumpIfTrue -) { - emitAddressMask(); - emitClearITState(state); - vmimtCondJump( - flag, - jumpIfTrue, - ji->linkPC, - state->info.t, - ji->linkReg, - ji->hint - ); -} - -// -// Jump to the label if the register masked with the mask is non-zero (if -// jumpIfNonZero) or zero (if !jumpIfNonZero) -// -static void emitJumpLabelOnMask( - armMorphStateP state, - Uns32 bits, - vmiLabelP label, - vmiReg reg, - Uns32 mask, - Bool jumpIfNonZero -) { - vmiCondition cond = jumpIfNonZero ? vmi_COND_NZ : vmi_COND_Z; - vmimtTestRCJumpLabel(bits, cond, reg, mask, label); -} - -// -// Emit code to interwork if required, depending on LSB of target address, or -// handle exception return -// -void armEmitInterworkLSB(armMorphStateP state, vmiReg ra) { - - Uns32 bits = ARM_GPR_BITS; - armP arm = state->arm; - vmiLabelP noSwitch = armEmitNewLabel(); - Bool inThumbMode = IN_THUMB_MODE(arm); - - // special behavior is required if this is a possible handler mode exception - // return - if(!IN_USER_MODE(arm)) { - - vmiLabelP noExceptionReturn = vmimtNewLabel(); - - // jump past exception return unless target address is the magic value - vmimtCompareRCJumpLabel( - bits, vmi_COND_C, ra, EXC_RETURN_MAGIC, noExceptionReturn - ); - - // jump past exception return unless processor is in handler mode - vmimtTestRCJumpLabel( - bits, vmi_COND_Z, ARM_PSR, PSR_EXCEPT_NUM, noExceptionReturn - ); - - // do exception return - vmimtArgProcessor(); - vmimtArgReg(bits, ra); - vmimtCall((vmiCallFn)armExceptionReturn); - - // here if not an exception return - vmimtInsertLabel(noExceptionReturn); - } - - // skip mode switch unless mode has changed - emitJumpLabelOnMask(state, bits, noSwitch, ra, 1, inThumbMode); - - // switch processor mode - armEmitInterwork(state); - - // here if no mode switch required - armEmitInsertLabel(noSwitch); -} - -// -// Check for mode switch depending on setting of bottom bit of target address -// -static void emitCheckSetMode(armMorphStateP state) { - - if(state->info.f) { - - // instruction variants that assign the PC and set flags are illegal - Uns32 bits = ARM_GPR_BITS; - - // update UFSR (CFSR) - vmimtBinopRC( - bits, vmi_OR, ARM_SCS_REG(SCS_ID(CFSR)), EXC_UNDEF_UNDEFINSTR, 0 - ); - - // take UsageFault exception - vmimtArgProcessor(); - vmimtArgSimPC(bits); - vmimtCall((vmiCallFn)armUsageFault); - - } else { - - // switch mode if LSB of PC implies a different mode - if(state->setMode) { - armEmitInterworkLSB(state, ARM_PC); - } - - // mask off LSB of target address - emitAddressMask(); - } -} - -// -// Perform an implicit unconditional direct jump if required -// -void armEmitImplicitUncondJump(armMorphStateP state) { - - switch(state->pcSet) { - - case ASPC_NA: - // no action unless PC was set by the instruction - break; - - case ASPC_R15: - // indirect jump to current value in R15 - emitCheckSetMode(state); - emitClearITState(state); - vmimtUncondJumpReg(0, ARM_PC, VMI_NOREG, vmi_JH_NONE); - break; - - case ASPC_R15_RET: - // return to current value in R15 - emitCheckSetMode(state); - emitClearITState(state); - vmimtUncondJumpReg(0, ARM_PC, VMI_NOREG, vmi_JH_RETURN); - break; - - case ASPC_IMM: - // direct jump to immediate address - emitClearITState(state); - vmimtUncondJump(0, state->pcImmediate, VMI_NOREG, vmi_JH_NONE); - break; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// INTRA-INSTRUCTION CONDITIONAL AND UNCONDITIONAL JUMPS -//////////////////////////////////////////////////////////////////////////////// - -// -// Create and return a new label -// -vmiLabelP armEmitNewLabel(void) { - return vmimtNewLabel(); -} - -// -// Insert a label previously created by vmimtNewLabel at the current location. -// -void armEmitInsertLabel(vmiLabelP label) { - vmimtInsertLabel(label); -} - -// -// Perform an unconditional jump to the passed local label. -// -void armEmitUncondJumpLabel(vmiLabelP toLabel) { - vmimtUncondJumpLabel(toLabel); -} - -// -// Perform a conditional jump if the condition flag is non-zero (jumpIfTrue) -// or zero (not jumpIfTrue). The target location is the passed local label. -// -void armEmitCondJumpLabel(vmiReg flag, Bool jumpIfTrue, vmiLabelP toLabel) { - vmimtCondJumpLabel(flag, jumpIfTrue, toLabel); -} - -// -// Test the register value by performing bitwise AND with the passed constant -// value, and jump to 'toLabel' if condition 'cond' is satisfied. -// -void armEmitTestRCJumpLabel( - Uns32 bits, - vmiCondition cond, - vmiReg r, - Uns64 c, - vmiLabelP toLabel -) { - vmimtTestRCJumpLabel(bits, cond, r, c, toLabel); -} - -// -// Compare the register value by performing subtraction of the passed constant -// value, and jump to 'toLabel' if condition 'cond' is satisfied. -// -void armEmitCompareRCJumpLabel( - Uns32 bits, - vmiCondition cond, - vmiReg r, - Uns64 c, - vmiLabelP toLabel -) { - vmimtCompareRCJumpLabel(bits, cond, r, c, toLabel); -} - - -//////////////////////////////////////////////////////////////////////////////// -// CALLBACK FUNCTION INTERFACE -//////////////////////////////////////////////////////////////////////////////// - -// -// Add processor argument to the stack frame -// -void armEmitArgProcessor(armMorphStateP state) { - vmimtArgProcessor(); -} - -// -// Add Uns32 argument to the stack frame -// -void armEmitArgUns32(armMorphStateP state, Uns32 arg) { - vmimtArgUns32(arg); -} - -// -// Add register argument to the stack frame -// -void armEmitArgReg(armMorphStateP state, Uns32 bits, vmiReg r) { - vmimtArgReg(bits, r); -} - -// -// Add program counter argument to the stack frame -// -void armEmitArgSimPC(armMorphStateP state, Uns32 bits) { - vmimtArgSimPC(bits); -} - -// -// Make a call with all current stack frame arguments -// -void armEmitCall(armMorphStateP state, vmiCallFn arg) { - vmimtCall(arg); -} - -// -// As above but generate a function result (placed in rd) -// -void armEmitCallResult( - armMorphStateP state, - vmiCallFn arg, - Uns32 bits, - vmiReg rd -) { - setVariable(state, rd, False); - vmimtCallResult(arg, bits, rd); - maskResult(rd); -} - - -//////////////////////////////////////////////////////////////////////////////// -// SIMULATOR CONTROL -//////////////////////////////////////////////////////////////////////////////// - -// -// Stop simulation of the current processor -// -void armEmitExit(void) { - vmimtExit(); -} - -// -// Emit code to wait for the passed reason -// -void armEmitWait(armMorphStateP state, armDisable reason) { - vmimtBinopRC(8, vmi_OR, ARM_DISABLE_REASON, reason, 0); - vmimtHalt(); -} - -// -// Terminate the current block -// -void armEmitEndBlock(void) { - vmimtEndBlock(); -} - -// -// Emit code to validate the current block mode -// -void armEmitValidateBlockMask(armBlockMask blockMask) { - vmimtValidateBlockMask(blockMask); -} - - diff --git a/simulators/ovp/armmModel/armmExceptions.c b/simulators/ovp/armmModel/armmExceptions.c deleted file mode 100644 index 5e7c0c0b..00000000 --- a/simulators/ovp/armmModel/armmExceptions.c +++ /dev/null @@ -1,2378 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -// Imperas header files -#include "hostapi/impAlloc.h" - -// VMI header files -#include "vmi/vmiMessage.h" -#include "vmi/vmiRt.h" -#include "vmi/vmiPorts.h" - -// model header files -#include "armConfig.h" -#include "armDecode.h" -#include "armExceptions.h" -#include "armFunctions.h" -#include "armMessage.h" -#include "armStructure.h" -#include "armSys.h" -#include "armSysRegisters.h" -#include "armUtils.h" -#include "armVariant.h" -#include "armVM.h" -#include "armVFP.h" - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_EXCEPTION" - -// -// This value is used when no exception priority is specified -// -#define EXC_NO_PRIORITY 0x7fffffff - - -//////////////////////////////////////////////////////////////////////////////// -// UTILITIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Return processor endianness -// -inline static memEndian getEndian(armP arm) { - return armGetEndian((vmiProcessorP)arm, False); -} - -// -// Is the processor halted? -// -inline static Bool isHalted(armP arm) { - return vmirtIsHalted((vmiProcessorP)arm); -} - -// -// Return current program counter -// -inline static Uns32 getPC(armP arm) { - return vmirtGetPC((vmiProcessorP)arm); -} - -// -// Return current program counter -// -inline static const char *getName(armP arm) { - return vmirtProcessorName((vmiProcessorP)arm); -} - -// -// Get vector table base address -// -inline static Uns32 getVectorTable(armP arm) { - return SCS_REG_UNS32(arm, VTOR) & 0x3fffff80; -} - -// -// Jump to address -// -inline static void setPC(armP arm, Uns32 newPC) { - vmirtSetPC((vmiProcessorP)arm, newPC); -} - -// -// Jump to exception vector -// -inline static void setPCException(armP arm, Uns32 newPC) { - vmirtSetPCException((vmiProcessorP)arm, newPC); -} - -// -// Is the processor in handler mode (note special case when sleep on ISR return) -// -inline static Bool inHandlerMode(armP arm) { - return IN_HANDLER_MODE(arm) && !arm->sleepOnExit; -} - -// -// Load a value from the passed memory domain, returning a boolean indicating if -// the load succeeded -// -static Bool loadWord(armP arm, memDomainP domain, Uns32 address, Uns32 *result) { - - // do the read - *result = vmirtRead4ByteDomain(domain, address, getEndian(arm), MEM_AA_TRUE); - - // indicate whether the write succeeded - return (arm->derivedException==AEN_None); -} - -// -// Store a value to the passed memory domain, returning a boolean indicating if -// the store succeeded -// -static Bool storeWord(armP arm, memDomainP domain, Uns32 address, Uns32 value) { - - // do the write - vmirtWrite4ByteDomain(domain, address, getEndian(arm), value, MEM_AA_TRUE); - - // indicate whether the write succeeded - return (arm->derivedException==AEN_None); -} - -// -// Load a value from the default system address map domain, returning a boolean -// indicating if the load succeeded -// -static Bool loadWordDefault(armP arm, Uns32 address, Uns32 *result) { - - // save current derived exception and context - armExceptNum oldDerivedException = arm->derivedException; - armExceptCxt oldContext = arm->exceptionContext; - Bool ok; - - // reset derived exception and context - arm->derivedException = AEN_None; - arm->exceptionContext = AEC_ReadVector; - - // do the load using default address map, restoring previous derived - // exception if it succeeds - if((ok=loadWord(arm, arm->dds.system, address, result))) { - arm->derivedException = oldDerivedException; - } - - // restore previous context - arm->exceptionContext = oldContext; - - return ok; -} - -// -// Write a value to the passed net -// -inline static void writeNet(armP arm, Uns32 netHandle, Uns32 value) { - if(netHandle) { - vmirtWriteNetPort((vmiProcessorP)arm, netHandle, value); - } -} - -// -// Suspend the executing processor -// -static void suspend(armP arm, Uns32 haltPC, armDisable reason) { - - arm->disableReason |= reason; - - setPC(arm, haltPC); - - vmirtHalt((vmiProcessorP)arm); -} - -// -// Enter lockup state -// -static void lockup(armP arm, Uns32 haltPC) { - - suspend(arm, haltPC, AD_LOCKUP); - - writeNet(arm, arm->lockup, 1); - - if(ARM_DEBUG_EXCEPT(arm)) { - vmiMessage("W", CPU_PREFIX "LOCKUP", - "ARM %s lock up at 0x%08x\n", - getName(arm), haltPC - ); - } -} - -// -// If the processor was waiting for the passed reason, restart it and return -// True; otherwise, return False -// -static Bool restart(armP arm, armDisable reason) { - - if(arm->disableReason) { - - arm->disableReason &= ~reason; - - if(!arm->disableReason) { - vmirtRestartNext((vmiProcessorP)arm); - return True; - } - } - - return False; -} - - -//////////////////////////////////////////////////////////////////////////////// -// EXCEPTION INFORMATION (FOR DEBUGGER INTEGRATION) -//////////////////////////////////////////////////////////////////////////////// - -// -// Helper macro for creation of exception entry in exceptions table -// -#define ARM_EXCEPTION_INFO(_D) [AEN_##_D] = {name:#_D, code:AEN_##_D} - -// -// Helper macro for creation of interrupt entry in exceptions table -// -#define ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, MINOR_S, MINOR_N) \ - [(_MAJOR_N*16)+MINOR_N+16] = { \ - name : "ExternalInt"#_MAJOR_S#MINOR_S, \ - code : (_MAJOR_N*16)+MINOR_N+16 \ - } - -// -// Helper macro for creation of 16 interrupt entries in exceptions table -// -#define ARM_INTERRUPT_INFOx16(_MAJOR_S, _MAJOR_N) \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 0, 0), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 1, 1), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 2, 2), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 3, 3), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 4, 4), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 5, 5), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 6, 6), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 7, 7), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 8, 8), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, 9, 9), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, a, 10), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, b, 11), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, c, 12), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, d, 13), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, e, 14), \ - ARM_INTERRUPT_INFO(_MAJOR_S, _MAJOR_N, f, 15) \ - -// -// Table of exception mode descriptors -// -static const vmiExceptionInfo exceptions[AEN_LAST] = { - ARM_EXCEPTION_INFO(Reset), - ARM_EXCEPTION_INFO(NMI), - ARM_EXCEPTION_INFO(HardFault), - ARM_EXCEPTION_INFO(MemManage), - ARM_EXCEPTION_INFO(BusFault), - ARM_EXCEPTION_INFO(UsageFault), - ARM_EXCEPTION_INFO(SVCall), - ARM_EXCEPTION_INFO(DebugMonitor), - ARM_EXCEPTION_INFO(PendSV), - ARM_EXCEPTION_INFO(SysTick), - ARM_INTERRUPT_INFOx16(00, 0), - ARM_INTERRUPT_INFOx16(01, 1), - ARM_INTERRUPT_INFOx16(02, 2), - ARM_INTERRUPT_INFOx16(03, 3), - ARM_INTERRUPT_INFOx16(04, 4), - ARM_INTERRUPT_INFOx16(05, 5), - ARM_INTERRUPT_INFOx16(06, 6), - ARM_INTERRUPT_INFOx16(07, 7), - ARM_INTERRUPT_INFOx16(08, 8), - ARM_INTERRUPT_INFOx16(09, 9), - ARM_INTERRUPT_INFOx16(0a, 10), - ARM_INTERRUPT_INFOx16(0b, 11), - ARM_INTERRUPT_INFOx16(0c, 12), - ARM_INTERRUPT_INFOx16(0d, 13), - ARM_INTERRUPT_INFOx16(0e, 14), - ARM_INTERRUPT_INFOx16(0f, 15), - ARM_INTERRUPT_INFOx16(10, 16), - ARM_INTERRUPT_INFOx16(11, 17), - ARM_INTERRUPT_INFOx16(12, 18), - ARM_INTERRUPT_INFOx16(13, 19), - ARM_INTERRUPT_INFOx16(14, 20), - ARM_INTERRUPT_INFOx16(15, 21), - ARM_INTERRUPT_INFOx16(16, 22), - ARM_INTERRUPT_INFOx16(17, 23), - ARM_INTERRUPT_INFOx16(18, 24), - ARM_INTERRUPT_INFOx16(19, 25), - ARM_INTERRUPT_INFOx16(1a, 26), - ARM_INTERRUPT_INFOx16(1b, 27), - ARM_INTERRUPT_INFOx16(1c, 28), - ARM_INTERRUPT_INFOx16(1d, 29), - ARM_INTERRUPT_INFOx16(1e, 30) -}; - -// -// Return the current processor exception -// -VMI_GET_EXCEPTION_FN(armGetException) { - armP arm = (armP)processor; - return &exceptions[arm->enabledException]; -} - -// -// Exception mode iterator -// -VMI_EXCEPTION_INFO_FN(armExceptionInfo) { - - armP arm = (armP)processor; - Uns32 intNum = NUM_INTERRUPTS(arm); - armExceptNum last = intNum+16; - vmiExceptionInfoCP end = exceptions+last; - vmiExceptionInfoCP this; - - // on the first call, start with the first member of the table - if(!prev) { - prev = exceptions-1; - } - - // search for the next member with seeded name - for(this=prev+1; this!=end; this++) { - if(this->name) { - return this; - } - } - - // no more exceptions - return 0; -} - - -//////////////////////////////////////////////////////////////////////////////// -// MODE INFORMATION (FOR DEBUGGER INTEGRATION) -//////////////////////////////////////////////////////////////////////////////// - -// -// Table of processor mode descriptions -// -static const vmiModeInfo modes[] = { - {name:"Thread", code:0}, - {name:"Handler", code:1}, - {0} -}; - -// -// Processor mode iterator -// -VMI_MODE_INFO_FN(armModeInfo) { - - // on the first call, start with the first member of the table - if(!prev) { - prev = modes-1; - } - - vmiModeInfoCP this = prev+1; - - return this->name ? this : 0; -} - -// -// Return the current processor mode -// -VMI_GET_MODE_FN(armGetMode) { - armP arm = (armP)processor; - return &modes[IN_HANDLER_MODE(arm)]; -} - - -//////////////////////////////////////////////////////////////////////////////// -// EXCEPTION ACTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// This specifies valid combinations for exception return -// -typedef enum armExcReturnTypeE { - AXRT_HANDLER_MAIN = 1, - AXRT_THREAD_MAIN = 9, - AXRT_THREAD_PROCESS = 13 -} armExcReturnType; - -// -// This macro returns a mask to select sub-priority bits -// -#define SUB_PRI_MASK(_A) ((2<xPriority[num] & ~SUB_PRI_MASK(arm)); -} - -// -// Return the sub-priority of the numbered exception -// NOTE: AEN_Reset, AEN_NMI and AEN_HardFault always return zero -// -inline static Uns32 subPriority(armP arm, armExceptNum num) { - return arm->xPriority[num] & SUB_PRI_MASK(arm); -} - -// -// Is the numbered exception enabled? -// -inline static Bool isEnabled(armP arm, armExceptNum num) { - return ( - EX_MASK_GET(arm->xEnable, num) && - (groupPriority(arm, num)executionPriority) - ); -} - -// -// Return the number of any pending enabled exception that should be taken now, -// assuming the processor is in the mode specified -// -static armExceptNum exceptionEnabled(armP arm, Bool handlerMode) { - - armExceptNum num = arm->enabledException; - - // return the selected exception if it has a priority number less than the - // current priority - if(num==AEN_None) { - return num; - } else if(!handlerMode) { - return num; - } else if(groupPriority(arm, num)executionPriority) { - return num; - } else { - return AEN_None; - } -} - -// -// Take exception immediately if required (may require processor restart) -// -static void takeExceptionNow(armP arm) { - - armExceptNum exceptNum = exceptionEnabled(arm, inHandlerMode(arm)); - - if(exceptNum && (!arm->disableReason || restart(arm, AD_WFI|AD_WFE))) { - vmirtDoSynchronousInterrupt((vmiProcessorP)arm); - } -} - -// -// Type representing number and priority of an exception -// -typedef struct exceptionDescS { - armExceptNum num; // exception number - Int32 groupPri; // exception group priority - Uns32 subPri; // exception sub-priority -} exceptionDesc, *exceptionDescP; - -// -// Update exceptionDesc to the passed exception if it is the highest priority -// one found so far -// -static void selectHighestPriority( - armP arm, - exceptionDescP desc, - armExceptNum num -) { - Int32 groupPri = groupPriority(arm, num); - Uns32 subPri = subPriority(arm, num); - - if( - // this is the highest group priority exception - (groupPrigroupPri) || - // this is the highest sub-priority exception - ((groupPri==desc->groupPri) && (subPrisubPri)) - ) { - desc->num = num; - desc->groupPri = groupPri; - desc->subPri = subPri; - } -} - -// -// Recalculate the boosted execution priority -// -static void refreshBoostedPriority(armP arm) { - - Int32 oldPriority = arm->executionPriority; - Int32 newPriority = arm->unboostedPriority; - Int32 BASEPRI = arm->sregs.BASEPRI; - - // allow for FAULTMASK, PRIMASK and BASEPRI execution priority boost - if(arm->sregs.FAULTMASK && (newPriority>-1)) { - newPriority = -1; - } else if(arm->sregs.PRIMASK && (newPriority>0)) { - newPriority = 0; - } else if(BASEPRI && (newPriority>BASEPRI)) { - newPriority = BASEPRI; - } - - // has execution priority changed? - if(oldPriority != newPriority) { - - // report execution priority change - if(ARM_DEBUG_EXCEPT(arm)) { - vmiPrintf( - "Execution priority %d -> %d\n", - oldPriority, newPriority - ); - } - - // save the new priority - arm->executionPriority = newPriority; - - // if the MPU is generally enabled but disabled when in a handler with - // negative execution priority (MPU_CONTROL.HFNMIENA=0), the MPU must be - // *disabled* when the old priority is non-negative and the new priority - // is negative, and *enabled* if the priority is negative and the new - // priority is non-negative - if(MPU_ENABLED(arm) && !SCS_FIELD(arm, MPU_CONTROL, HFNMIENA)) { - - Bool oldNegative = (oldPriority<0); - Bool newNegative = (newPriority<0); - - if(oldNegative!=newNegative) { - armSwitchMode(arm); - } - } - } -} - -// -// Recalculate the unboosted execution priority -// -static void refreshUnboostedPriority(armP arm) { - - exceptionDesc desc = {num:AEN_None, groupPri:EXC_NO_PRIORITY}; - Uns32 index; - - // process array of active exceptions, high to low priority - for(index=0; indexexceptMaskNum; index++) { - - Uns32 entry = arm->xActive[index]; - - if(entry) { - - Uns32 bit = 0; - Uns32 mask = 1; - - do { - - // is this bit selected? - if(entry & mask) { - - // calculate armExceptNum for this index/bit pair - armExceptNum num = (index*32) + bit; - - // select the exception if it is higher priority than any - // found so far - selectHighestPriority(arm, &desc, num); - - // remove the selected bit from the mask - entry &= ~mask; - } - - // step to the next bit - mask <<= 1; - bit++; - - } while(entry); - } - } - - // save the new unboosted priority - arm->unboostedPriority = desc.groupPri; - - // refresh the boosted priority - refreshBoostedPriority(arm); -} - -// -// Calculate the highest-priority pending exception number -// -static void refreshPendingException(armP arm) { - - exceptionDesc enabledDesc = {num:AEN_None, groupPri:EXC_NO_PRIORITY}; - exceptionDesc pendingDesc = {num:AEN_None, groupPri:EXC_NO_PRIORITY}; - Uns32 index; - - // assume no interrupts are pending initially - arm->pendingInterrupt = False; - - // process array of pending exceptions, high to low priority - for(index=0; indexexceptMaskNum; index++) { - - Uns32 entry = arm->xPend[index]; - - if(entry) { - - Uns32 bit = 0; - Uns32 mask = 1; - - do { - - // is this bit selected? - if(entry & mask) { - - // calculate armExceptNum for this index/bit pair - armExceptNum num = (index*32) + bit; - - // set ICSR.ISRPENDING if this is a pending interrupt - if(num>=AEN_ExternalInt0) { - arm->pendingInterrupt = True; - } - - // find the highest priority pending exception (regardless - // of enabled) - selectHighestPriority(arm, &pendingDesc, num); - - // find the highest priority enabled exception - if(isEnabled(arm, num)) { - selectHighestPriority(arm, &enabledDesc, num); - } - - // remove the selected bit from the mask - entry &= ~mask; - } - - // step to the next bit - mask <<= 1; - bit++; - - } while(entry); - } - } - - // has highest-priority pending exception changed? - if(arm->pendingException != pendingDesc.num) { - - // report execution priority change - if(ARM_DEBUG_EXCEPT(arm)) { - vmiPrintf( - "Pending exception %u -> %u (priority %d)\n", - arm->pendingException, pendingDesc.num, pendingDesc.groupPri - ); - } - - // save the highest-priority pending exception - arm->pendingException = pendingDesc.num; - } - - // has highest-priority enabled exception changed? - if(arm->enabledException != enabledDesc.num) { - - // report execution priority change - if(ARM_DEBUG_EXCEPT(arm)) { - vmiPrintf( - "Enabled exception %u -> %u (priority %d)\n", - arm->enabledException, enabledDesc.num, enabledDesc.groupPri - ); - } - - // save the highest-priority pending exception - arm->enabledException = enabledDesc.num; - } -} - -// -// Derive value of ICSR.RETTOBASE -// -Bool armGetRetToBase(armP arm) { - - Uns32 index; - - // process array of active exceptions - for(index=0; indexexceptMaskNum; index++) { - - Uns32 entry = arm->xActive[index]; - - if(entry) { - - Uns32 bit = 0; - Uns32 mask = 1; - - do { - - // is this bit selected? - if(entry & mask) { - - // calculate armExceptNum for this index/bit pair - armExceptNum thisNum = (index*32) + bit; - - // return False if the active exception is not the currently - // executing one - if(thisNum != PSR_FIELD(arm, exceptNum)) { - return False; - } - - // remove the selected bit from the mask - entry &= ~mask; - } - - // step to the next bit - mask <<= 1; - bit++; - - } while(entry); - } - } - - // no other exceptions are active - return True; -} - -// -// ARMv7-M ClearExclusiveLocal implementation -// -inline static void clearExclusiveLocal(armP arm) { - arm->exclusiveTag = ARM_NO_TAG; -} - -// -// ARMv7-M ARM SetEventRegister implementation -// -inline static void setEventRegister(armP arm) { - arm->eventRegister = !restart(arm, AD_WFE); -} - -// -// ARMv7-M ARM Raise implementation -// -static void raise(armP arm, armExceptNum num) { - - // restart the processor on reset, or if it is waiting-for-event and - // SCR.SEVONPEND is set - if(num==AEN_Reset) { - restart(arm, AD_WFE|AD_WFI|AD_LOCKUP); - } else if(!EX_MASK_GET(arm->xPend, num) && SCS_FIELD(arm, SCR, SEVONPEND)) { - restart(arm, AD_WFE); - } - - // set pending bit AFTER restart - EX_MASK_SET_1(arm->xPend, num); - - // refresh pending exception - refreshPendingException(arm); -} - -// -// ARMv7-M ARM Raise implementation, takes effect next instruction -// -inline static void raiseNext(armP arm, armExceptNum num) { - - raise(arm, num); -} - -// -// ARMv7-M ARM Raise implementation, takes effect immediately -// -inline static void raiseNow(armP arm, armExceptNum num) { - - raise(arm, num); - - // refresh pending exception - takeExceptionNow(arm); -} - -// -// ARMv7-M ARM Lower implementation -// -static void lower(armP arm, armExceptNum num) { - - EX_MASK_SET_0(arm->xPend, num); - - // refresh pending exception - if(num==arm->enabledException) { - refreshPendingException(arm); - } -} - -// -// ARMv7-M ARM Activate implementation -// -static void activate(armP arm, armExceptNum num) { - - EX_MASK_SET_0(arm->xPend, num); - EX_MASK_SET_1(arm->xActive, num); - - arm->nestedActivation++; - - // refresh execution priority and pending exception - refreshUnboostedPriority(arm); - refreshPendingException(arm); -} - -// -// ARMv7-M ARM Deactivate implementation -// -static void deactivate(armP arm, armExceptNum num) { - - EX_MASK_SET_0(arm->xActive, num); - - // clear FAULTMASK on any return except NMI - if(PSR_FIELD(arm, exceptNum) != AEN_NMI) { - arm->sregs.FAULTMASK = 0; - } - - arm->nestedActivation--; - - // refresh execution priority and pending exception - refreshUnboostedPriority(arm); - refreshPendingException(arm); -} - -// -// ARMv7-M ARM DeactivateAll implementation -// -static void deactivateAll(armP arm) { - - Uns32 i; - - // set all exceptions inactive - for(i=0; iexceptMaskNum; i++) { - arm->xPend [i] = 0; - arm->xActive[i] = 0; - } - - arm->nestedActivation = 0; - - // refresh execution priority and pending exception - refreshUnboostedPriority(arm); - refreshPendingException(arm); -} - -// -// This is the UpdateFPCCR psuedo-code function -// Called on exception entry when lazy context save is active -// -static void updateFPCCR(armP arm, Uns32 frameptr, memDomainP domain) { - - if (CONTROL_FIELD(arm, FPCA) && SCS_FIELD(arm, FPCCR, LSPEN)) { - - Uns32 fpFramePtr = frameptr + 0x20; - Uns32 pri = arm->executionPriority; - - // Save the pointer to the unfilled space on the stack for the FP state - // (also save the domain to use with the pointer) - SCS_FIELD(arm, FPCAR, ADDRESS) = fpFramePtr >> 3; - arm->FPCARdomain = domain; - - armUpdateLSPACT(arm, 1); - - SCS_FIELD(arm, FPCCR, USER) = IN_USER_MODE(arm); - SCS_FIELD(arm, FPCCR, THREAD) = !IN_HANDLER_MODE(arm); - SCS_FIELD(arm, FPCCR, HFRDY) = pri > -1; - SCS_FIELD(arm, FPCCR, BFRDY) = EX_MASK_GET(arm->xEnable, AEN_BusFault) && (pri > arm->xPriority[AEN_BusFault]); - SCS_FIELD(arm, FPCCR, MMRDY) = EX_MASK_GET(arm->xEnable, AEN_MemManage) && (pri > arm->xPriority[AEN_MemManage]); - SCS_FIELD(arm, FPCCR, MONRDY) = EX_MASK_GET(arm->xEnable, AEN_DebugMonitor) && (pri > arm->xPriority[AEN_DebugMonitor]); - - } -} - -// -// Run-time check if the VFP is currently enabled for the current mode -// TODO: Should this use the mode being returned to?? -// -static Bool doVFPEnabled(armP arm) { - - Bool inUserMode = IN_USER_MODE(arm); - Uns32 cp10Enable = SCS_FIELD(arm, CPACR, cp10); - Bool enabled = True; - - // check CPACR for permission to use cp10 (and cp11) in the current user/privilege mode - if(inUserMode && !(cp10Enable&2)) { - enabled = False; - } else if(!inUserMode && !(cp10Enable&1)) { - enabled = False; - } - - if (!enabled) { - // VFP disabled - usage fault - SCS_FIELD(arm, CFSR, NOCP) = 1; - arm->derivedException = AEN_UsageFault; - return False; - } - - return True; - -} - -// -// Save the FP state on the exception stack frame -// -static Bool pushFP(armP arm, Uns32 fpFramePtr, memDomainP domain) { - - Uns32 i; - - for (i = 0; i < 16; i++) { - if (!storeWord(arm, domain, fpFramePtr+(i*4), FP_REG(arm, i))) - return False; - } - - if (!storeWord(arm, domain, fpFramePtr+64, FPSCR_REG(arm))) { - return False; - } - - return True; - -} - -// -// ARMv7-M ARM PushStack implementation -// -static void pushStack(armP arm, memDomainP domain, Uns32 returnAddress) { - - // NOTE: stack pointer currently in arm->regs[ARM_REG_SP] is always - // consistent with CONTROL.useSP_Process at this point - // TODO: When this is updated to support FP, must also update armmCpuHelper - Bool haveFPExt = FPU_PRESENT(arm); - Bool fpCtxtActive = haveFPExt && CONTROL_FIELD(arm, FPCA); - Uns32 frameSize = fpCtxtActive ? 0x68 : 0x20; - Uns32 frameptr = arm->regs[ARM_REG_SP] - frameSize; - Bool frameptralign = (SCS_FIELD(arm, CCR, STKALIGN) || fpCtxtActive) && (frameptr&4); - - // allow for alignment - if(frameptralign) { - frameptr &= ~4; - } - - // save modified stack pointer - arm->regs[ARM_REG_SP] = frameptr; - - // get the PSR and modify the align4 field - armPSR tmpPSR = {reg:armReadCPSR(arm)}; - tmpPSR.fields.align4 = frameptralign; - Uns32 value = tmpPSR.reg; - - // save the registers, terminating on derived exception - if (storeWord(arm, domain, frameptr, arm->regs[0] ) && - storeWord(arm, domain, frameptr+0x4, arm->regs[1] ) && - storeWord(arm, domain, frameptr+0x8, arm->regs[2] ) && - storeWord(arm, domain, frameptr+0xc, arm->regs[3] ) && - storeWord(arm, domain, frameptr+0x10, arm->regs[12] ) && - storeWord(arm, domain, frameptr+0x14, arm->regs[ARM_REG_LR]) && - storeWord(arm, domain, frameptr+0x18, returnAddress ) && - storeWord(arm, domain, frameptr+0x1c, value )) - { - // if normal stack context successfully saved then save FP context if indicated - if (fpCtxtActive) { - if (SCS_FIELD(arm, FPCCR, LSPEN) == 0) { - if (doVFPEnabled(arm)) { - pushFP(arm, frameptr+0x20, domain); - } - } else { - updateFPCCR(arm, frameptr, domain); - } - } - } - - // determine exception return type - armExcReturnType returnType; - - if(inHandlerMode(arm)) { - returnType = AXRT_HANDLER_MAIN; - } else if(!USE_SP_PROCESS(arm)) { - returnType = AXRT_THREAD_MAIN; - } else { - returnType = AXRT_THREAD_PROCESS; - } - - // update LR for correct return behavior - if (fpCtxtActive) { - // Bit 4 = 0 indicates fp context was active - arm->regs[ARM_REG_LR] = 0xffffffe0 | returnType; - } else { - arm->regs[ARM_REG_LR] = 0xfffffff0 | returnType; - } -} - -// -// Restore the FP state from the exception stack frame -// -static Bool popFP(armP arm, Uns32 frameptr, Uns32 *fp, memDomainP domain, Bool *restore) { - - *restore = False; - - if (SCS_FIELD(arm, FPCCR, LSPACT)) { - - // State in FP is still valid, do not need to restore - armUpdateLSPACT(arm, 0); - - } else if (!doVFPEnabled(arm)) { - - // VFP disabled - usage fault generated - return False; - - } else { - - // Restore fp state, aborting if error occurs - Uns32 fpFramePtr = frameptr + 0x20; - Uns32 i; - - for (i = 0; i < 16; i++) { - if (!loadWord(arm, domain, fpFramePtr+(i*4), fp+i)) - return False; - } - - if (!loadWord(arm, domain, fpFramePtr+64, fp+16)) { - return False; - } - - *restore = True; - } - - return True; -} - -// -// ARMv7-M ARM PopStack implementation -// -static void popStack(armP arm, Uns32 targetPC, memDomainP domain, Bool requiredHandlerMode) { - - // these hold intermediate values prior to commit - Uns32 r0, r1, r2, r3, r12, lr, pc, psr, fp[17]; - Bool restoreFP = False; - - // NOTE: stack pointer currently in arm->regs[ARM_REG_SP] is always - // consistent with CONTROL.useSP_Process at this point - Bool haveFPExt = FPU_PRESENT(arm); - Bool fpca = (targetPC & 0x10) == 0; - Bool fpCtxtActive = haveFPExt && fpca; - Uns32 frameSize = fpCtxtActive ? 0x68 : 0x20; - Uns32 frameptr = arm->regs[ARM_REG_SP]; - - // load stack frame, terminating on derived exception - if( - loadWord(arm, domain, frameptr, &r0 ) && - loadWord(arm, domain, frameptr+0x4, &r1 ) && - loadWord(arm, domain, frameptr+0x8, &r2 ) && - loadWord(arm, domain, frameptr+0xc, &r3 ) && - loadWord(arm, domain, frameptr+0x10, &r12) && - loadWord(arm, domain, frameptr+0x14, &lr ) && - loadWord(arm, domain, frameptr+0x18, &pc ) && - loadWord(arm, domain, frameptr+0x1c, &psr) && - (!fpCtxtActive || popFP(arm, frameptr, fp, domain, &restoreFP)) - ) { - - // extract PSR fields - armPSR tmpPSR = {reg:psr}; - Bool actualHandlerMode = tmpPSR.fields.exceptNum && True; - - // if fp exists restore the fpca value that existed on exception entry - if (haveFPExt) { - armUpdateFPCA(arm, fpca); - } - - // 1. must be returning to Thumb mode - // 2. must be returning to consistent Handler mode - if(!(tmpPSR.fields.T && (requiredHandlerMode==actualHandlerMode))) { - - SCS_FIELD(arm, CFSR, INVPC) = 1; - arm->derivedException = AEN_UsageFault; - - } else { - - // commit loaded values - arm->regs[0] = r0; - arm->regs[1] = r1; - arm->regs[2] = r2; - arm->regs[3] = r3; - arm->regs[12] = r12; - arm->regs[ARM_REG_LR] = lr; - if (restoreFP) { - Uns32 i; - for (i = 0; i < 16; i++) { - FP_REG(arm, i) = fp[i]; - } - FPSCR_REG(arm) = fp[16]; - } - - // commit PC (NOTE: least significant bit should be zero, but we mask it - // here to be sure) - setPC(arm, pc & ~1); - - // adjust stack pointer - // NOTE: stack pointer currently in arm->regs[ARM_REG_SP] is - // always consistent with CONTROL.useSP_Process at this point - arm->regs[ARM_REG_SP] += frameSize; - - // restore 4-byte alignment if required - if(tmpPSR.fields.align4 && (SCS_FIELD(arm, CCR, STKALIGN) || fpCtxtActive)) { - arm->regs[ARM_REG_SP] |= 4; - } - - // write valid PSR bits - armWriteCPSR(arm, psr, PSR_ALL); - } - } -} - -// -// Do reset exception -// -static void takeReset(armP arm) { - - Uns32 table = getVectorTable(arm); - - // these hold intermediate values prior to commit - Uns32 sp, pc; - - // get initial values of spMain and PC - if( - loadWordDefault(arm, table, &sp) && - loadWordDefault(arm, table+4, &pc) - ) { - // reset stack pointers and link register - arm->regs[ARM_REG_SP] = sp & 0xfffffffc; - arm->bank.R13_process = 0; - arm->regs[ARM_REG_LR] = 0xffffffff; - - // set PSR - armPSR psr = {fields:{T:pc&1}}; - armWriteCPSR(arm, psr.reg, PSR_ALL); - - // force other special registers to reset value (effects of this are - // accounted for in deactivateAll below) - arm->sregs.CONTROL.reg = 0; - arm->sregs.PRIMASK = 0; - arm->sregs.FAULTMASK = 0; - arm->sregs.BASEPRI = 0; - - // reset system state and VM structures - armSysReset(arm); - armVMReset(arm); - armFPReset(arm); - - // Set the block mask since regs with fields in block mask have been reset - armSetBlockMask(arm); - - // deactivate all exceptions - deactivateAll(arm); - - // processor is not in exclusive access mode - clearExclusiveLocal(arm); - setEventRegister(arm); - - // jump to reset address (Thumb mode bit masked off) - setPCException(arm, pc & ~1); - } -} - -// -// Do common exception actions -// -static void takeException(armP arm, armExceptNum exceptionNumber) { - - Uns32 table = getVectorTable(arm); - Uns32 pc; - - // get vector address - if(loadWordDefault(arm, table+(4*exceptionNumber), &pc)) { - - // set PSR (all fields except flags) - armPSR psr = {fields:{T:pc&1, exceptNum:exceptionNumber}}; - armWriteCPSR(arm, psr.reg, PSR_NOT_FLAGS); - - // Clear CONTROL.FPCA if FP present - // Note: Documentation says to set to 1 here but that makes no sense!!!! - if (FPU_PRESENT(arm)) { - armUpdateFPCA(arm, 0); - } - - // current stack is Main - armWriteSPProcess(arm, False); - - // activate exception - activate(arm, exceptionNumber); - - // processor is not in exclusive access mode - clearExclusiveLocal(arm); - setEventRegister(arm); - - // if this is an interrupt, signal to any external interrupt controller - // that it is being serviced - if(exceptionNumber>=AEN_ExternalInt0) { - writeNet(arm, arm->intISS, exceptionNumber-AEN_ExternalInt0); - } - - // jump to exception vector (Thumb mode bit masked off) - setPCException(arm, pc & ~1); - } -} - -// -// Escalate priority to AEN_HardFault if this exception is not enabled or lower -// or equal priority to the execution priority -// -static armExceptNum escalatePriority(armP arm, armExceptNum exceptionNumber) { - - if(isEnabled(arm, exceptionNumber)) { - return exceptionNumber; - } else if(exceptionNumber==AEN_DebugMonitor) { - SCS_FIELD(arm, HFSR, DEBUGEVT) = 1; - } else { - SCS_FIELD(arm, HFSR, FORCED) = 1; - } - - return AEN_HardFault; -} - -// -// Return the memory domain to use for pushStack/popStack when executing with -// the passed priority -// -static memDomainP getPriorityStackDomain(armP arm, Int32 priority) { - if(!MPU_ENABLED(arm)) { - return arm->dds.system; - } else if(priority>=0) { - return arm->dds.vmPriv; - } else if(SCS_FIELD(arm, MPU_CONTROL, HFNMIENA)) { - return arm->dds.vmPriv; - } else { - return arm->dds.system; - } -} - -// -// Do common actions at start of attempt to take exception - actual exception -// taken may be an escalated one -// -static void startException( - armP arm, - armExceptNum exceptionNumber, - Uns32 returnAddress -) { - Int32 oldPriority = arm->executionPriority; - Bool lockupDerived; - - if(arm->exceptionContext == AEC_PreserveFPState) { - // TODO: Remove this when this exception is fully modeled - vmiMessage("E", CPU_PREFIX "_LFPSPE", "Exceptions during lazy FP state preservation not supported yet"); - vmirtStop(); - } - - // restore normal data domain for this mode (in case this exception is a - // result of LDRT or STRT, for example) - if(arm->restoreDomain) { - armVMRestoreNormalDataDomain(arm); - } - - // escalate priority to AEN_HardFault if this exception is not enabled - // or lower or equal priority to the execution priority - exceptionNumber = escalatePriority(arm, exceptionNumber); - - // indicate that we are entering the exception prologue - arm->exceptionContext = AEC_PushStack; - arm->derivedException = AEN_None; - - // do exception-specific actions - if(exceptionNumber==AEN_Reset) { - - // any derived exception here causes lockup - lockupDerived = True; - - // do reset operations - takeReset(arm); - - } else { - - // any derived exception here causes lockup only if the current priority - // is negative - lockupDerived = (oldPriority<0); - - // get the appropriate memory domain to use for vector reads and - // pushStack writes - Int32 priority = groupPriority(arm, exceptionNumber); - memDomainP domain = getPriorityStackDomain(arm, priority); - - // save register state - pushStack(arm, domain, returnAddress); - - // take the exception unless pushStack created unrecoverable errors - if(!(lockupDerived && arm->derivedException)) { - takeException(arm, exceptionNumber); - } - } - - // if there is a derived exception, either activate it or enter lockup state - if(!arm->derivedException) { - // no action - } else if(lockupDerived) { - lockup(arm, 0xffffffff); - } else { - raiseNext(arm, escalatePriority(arm, arm->derivedException)); - } - - // indicate exception prologue is no longer active - arm->exceptionContext = AEC_None; -} - -// -// Take a derived exception (uses tail chaining) -// -static void derivedException( - armP arm, - armExceptNum exceptionNumber, - Uns32 targetPC -) { - // save target address in LR - arm->regs[ARM_REG_LR] = targetPC; - - // deactivate the running exception - deactivate(arm, PSR_FIELD(arm, exceptNum)); - - // take the derived exception (tail-chained) - takeException(arm, escalatePriority(arm, exceptionNumber)); -} - -// -// Should the processor sleet on exit from the exception? -// -inline static Bool doSleepOnExit(armP arm, armExceptNum exceptNum) { - return EX_IS_INTERRUPT(exceptNum) && SCS_FIELD(arm, SCR, SLEEPONEXIT); -} - -// -// Handle exception return -// -void armExceptionReturn(armP arm, Uns32 targetPC) { - - armExceptNum returningExceptionNumber = PSR_FIELD(arm, exceptNum); - armExcReturnType type = targetPC & EXC_RETURN_TYPE; - Bool handlerMode = (type==AXRT_HANDLER_MAIN); - - // sanity check we are being called in handler mode - VMI_ASSERT( - inHandlerMode(arm), - "require handler mode" - ); - - // sanity check this is indeed an exception return - VMI_ASSERT( - (targetPC&EXC_RETURN_MAGIC) == EXC_RETURN_MAGIC, - "targetPC is not an exception return address" - ); - - // initially assume no derived exception - arm->derivedException = AEN_None; - - if(!EX_MASK_GET(arm->xActive, returningExceptionNumber)) { - - // returning from inactive handler - SCS_FIELD(arm, CFSR, INVPC) = 1; - arm->derivedException = AEN_UsageFault; - - } else switch(type) { - - case AXRT_HANDLER_MAIN: - // return to Handler - if(arm->nestedActivation==1) { - SCS_FIELD(arm, CFSR, INVPC) = 1; - arm->derivedException = AEN_UsageFault; - } else { - armWriteSPProcess(arm, False); - } - break; - - case AXRT_THREAD_MAIN: - // return to Thread using Main stack - if((arm->nestedActivation!=1) && SCS_FIELD(arm, CCR, NONBASETHRDENA)) { - SCS_FIELD(arm, CFSR, INVPC) = 1; - arm->derivedException = AEN_UsageFault; - } else { - armWriteSPProcess(arm, False); - } - break; - - case AXRT_THREAD_PROCESS: - // return to Thread using Process stack - if((arm->nestedActivation!=1) && SCS_FIELD(arm, CCR, NONBASETHRDENA)) { - SCS_FIELD(arm, CFSR, INVPC) = 1; - arm->derivedException = AEN_UsageFault; - } else { - armWriteSPProcess(arm, True); - } - break; - - default: - // illegal EXC_RETURN - SCS_FIELD(arm, CFSR, INVPC) = 1; - arm->derivedException = AEN_UsageFault; - break; - } - - if(!arm->derivedException) { - - // get data domain *before* deactivating the exception (for popStack) - memDomainP domain = getPriorityStackDomain(arm, arm->executionPriority); - - // deactivate the terminating exception (NOTE: this can update execution - // priority and so affect the stack domain) - deactivate(arm, returningExceptionNumber); - - if(exceptionEnabled(arm, handlerMode)) { - - // take tail-chained exception - arm->regs[ARM_REG_LR] = targetPC; - takeException(arm, arm->enabledException); - - } else if(doSleepOnExit(arm, returningExceptionNumber)) { - - // return to top level with SCR.SLEEPONEXIT set should suspend the - // processor (reawaken it when the next interrupt comes in) - arm->regs[ARM_REG_LR] = targetPC; - suspend(arm, getPC(arm), AD_WFI); - arm->sleepOnExit = True; - - } else { - - // restore register state (may set arm->derivedException) - arm->exceptionContext = AEC_PopStack; - popStack(arm, targetPC, domain, handlerMode); - arm->exceptionContext = AEC_None; - - // error in load operations or inconsistent IPSR - reincrement - // nestedActivation (to undo the effect of deactivate above) - if(arm->derivedException) { - arm->nestedActivation++; - } - } - - // processor is not in exclusive access mode - clearExclusiveLocal(arm); - setEventRegister(arm); - } - - // handle any derived exception as a tail-chained one at higher activation - // depth - if(!arm->derivedException) { - // no action - } else if((arm->executionPriority<0) && (returningExceptionNumber==AEN_NMI)) { - lockup(arm, 0xffffffff); - } else { - derivedException(arm, arm->derivedException, targetPC); - } -} - -// -// Perform actions required for alignment fault -// -inline static void doAlign(armP arm) { - startException(arm, AEN_UsageFault, getPC(arm)); -} - -// -// Do breakpoint exception (prefetch abort) -// -void armBKPT(armP arm, Uns32 thisPC) { - - if(arm->executionPriority<0) { - lockup(arm, thisPC); - } else { - startException(arm, AEN_DebugMonitor, thisPC); - } -} - -// -// Do software exception -// -void armSWI(armP arm, Uns32 thisPC) { - - if(arm->executionPriority<0) { - lockup(arm, thisPC); - } else { - startException(arm, AEN_SVCall, thisPC+2); - } -} - -// -// Do UsageFault exception -// -void armUsageFault(armP arm, Uns32 thisPC) { - - if(arm->executionPriority<0) { - lockup(arm, thisPC); - } else { - startException(arm, AEN_UsageFault, thisPC); - } -} - -// -// Do BusFault exception -// -void armBusFault(armP arm, Uns32 faultAddress, memPriv priv) { - - Int32 priority = arm->executionPriority; - Bool ignoreFault = False; - Bool lockUpAtFFF = False; - - // clear valid bits - SCS_FIELD(arm, CFSR, BFARVALID) = 0; - - // update fault status - if(priv==MEM_PRIV_X) { - SCS_FIELD(arm, CFSR, IBUSERR) = 1; - } else if(arm->exceptionContext==AEC_PushStack) { - SCS_FIELD(arm, CFSR, STKERR) = 1; - } else if(arm->exceptionContext==AEC_PopStack) { - SCS_FIELD(arm, CFSR, UNSTKERR) = 1; - } else if(arm->exceptionContext==AEC_ReadVector) { - SCS_FIELD(arm, HFSR, VECTTBL) = 1; - lockUpAtFFF = True; - } else { - - SCS_FIELD(arm, CFSR, PRECISERR) = 1; - SCS_FIELD(arm, CFSR, BFARVALID) = 1; - SCS_REG_UNS32(arm, BFAR) = faultAddress; - - // ignore this fault if priority is negative and CCR.BFHFNMIGN is set - ignoreFault = (priority<0) && SCS_FIELD(arm, CCR, BFHFNMIGN); - } - - if(ignoreFault) { - // no action if fault is ignored for some reason - } else if(priority<0) { - arm->derivedException = AEN_HardFault; - lockup(arm, lockUpAtFFF ? 0xffffffff : getPC(arm)); - } else if(arm->exceptionContext == AEC_ReadVector) { - arm->derivedException = AEN_HardFault; - } else if(arm->exceptionContext != AEC_None) { - arm->derivedException = AEN_BusFault; - if(arm->exceptionContext == AEC_PreserveFPState) { - // TODO: Remove this when this exception is fully modeled - vmiMessage("E", CPU_PREFIX "_LFPSPE", "Exceptions during lazy FP state preservation not supported yet"); - vmirtStop(); - } - } else { - startException(arm, AEN_BusFault, getPC(arm)); - } -} - -// -// Do MemManage exception -// -void armMemoryAbort(armP arm, Uns32 faultAddress, memPriv priv) { - - // clear valid bits - SCS_FIELD(arm, CFSR, MMARVALID) = 0; - - // update fault status - if(priv==MEM_PRIV_X) { - SCS_FIELD(arm, CFSR, IACCVIOL) = 1; - } else if(arm->exceptionContext==AEC_PushStack) { - SCS_FIELD(arm, CFSR, MSTKERR) = 1; - } else if(arm->exceptionContext==AEC_PopStack) { - SCS_FIELD(arm, CFSR, MUNSTKERR) = 1; - } else { - SCS_FIELD(arm, CFSR, DACCVIOL) = 1; - SCS_FIELD(arm, CFSR, MMARVALID) = 1; - SCS_REG_UNS32(arm, MMAR) = faultAddress; - } - - // either take immediately or handle as a derived exception later - if(arm->executionPriority<0) { - arm->derivedException = AEN_MemManage; - lockup(arm, getPC(arm)); - } else if(arm->exceptionContext != AEC_None) { - arm->derivedException = AEN_MemManage; - if(arm->exceptionContext == AEC_PreserveFPState) { - // TODO: Remove this when this exception is fully modeled - vmiMessage("E", CPU_PREFIX "_LFPSPE", "Exceptions during lazy FP state preservation not supported yet"); - vmirtStop(); - } - } else { - startException(arm, AEN_MemManage, getPC(arm)); - } -} - -// -// Refresh execution priority on any state change which affects it -// -void armRefreshExecutionPriority(armP arm) { - - // refresh execution priority - Int32 oldPriority = arm->executionPriority; - refreshBoostedPriority(arm); - Int32 newPriority = arm->executionPriority; - - // if execution priority has been lowered, determine whether pending - // exception is now active - if((arm->pendingException!=AEN_None) && (newPriority>oldPriority)) { - - armExceptNum num = arm->pendingException; - Int32 priority = groupPriority(arm, num); - - if(priority %u (priority %d)\n", - arm->enabledException, num, priority - ); - } - - // save the highest-priority pending exception - arm->enabledException = num; - - // take exceptions now if required - takeExceptionNow(arm); - } - } -} - -// -// Refresh pending exception state on any state change which affects it -// -void armRefreshPendingException(armP arm) { - - // refresh pending exception - refreshPendingException(arm); - - // take exceptions now if required - takeExceptionNow(arm); -} - -// -// Refresh execution priority and pending exception state on any state change -// which affects them -// -void armRefreshExecutionPriorityPendingException(armP arm) { - - // refresh execution priority - refreshUnboostedPriority(arm); - refreshPendingException(arm); - - // take exceptions now if required - takeExceptionNow(arm); -} - - -//////////////////////////////////////////////////////////////////////////////// -// PRIVILEGE, ALIGNMENT AND FETCH EXCEPTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Read privilege exception handler -// -VMI_RD_PRIV_EXCEPT_FN(armRdPrivExceptionCB) { - - armP arm = (armP)processor; - Uns32 faultAddr = (Uns32)address; - memPriv priv = MEM_PRIV_R; - armVMAction action = armVMMiss(arm, priv, faultAddr, bytes, attrs); - - if(action == MA_OK) { - memDomainP domain = vmirtGetProcessorDataDomain(processor); - vmirtReadNByteDomain(domain, faultAddr, value, bytes, 0, attrs); - } -} - -// -// Write privilege exception handler -// -VMI_WR_PRIV_EXCEPT_FN(armWrPrivExceptionCB) { - - armP arm = (armP)processor; - Uns32 faultAddr = (Uns32)address; - memPriv priv = MEM_PRIV_W; - armVMAction action = armVMMiss(arm, priv, faultAddr, bytes, attrs); - - if(action == MA_OK) { - memDomainP domain = vmirtGetProcessorDataDomain(processor); - vmirtWriteNByteDomain(domain, faultAddr, value, bytes, 0, attrs); - } -} - -// -// Read alignment exception handler -// -VMI_RD_ALIGN_EXCEPT_FN(armRdAlignExceptionCB) { - - armP arm = (armP)processor; - - SCS_FIELD(arm, CFSR, UNALIGNED) = 1; - doAlign(arm); - - return 0; -} - -// -// Write alignment exception handler -// -VMI_WR_ALIGN_EXCEPT_FN(armWrAlignExceptionCB) { - - armP arm = (armP)processor; - - SCS_FIELD(arm, CFSR, UNALIGNED) = 1; - doAlign(arm); - - return 0; -} - -// -// Read abort exception handler (generated by calls to icmAbortRead in memory -// read callbacks) -// -VMI_RD_ABORT_EXCEPT_FN(armRdAbortExceptionCB) { - - armP arm = (armP)processor; - - if(isFetch) { - armBusFault(arm, address, MEM_PRIV_X); - } else { - armBusFault(arm, address, MEM_PRIV_R); - } -} - -// -// Write abort exception handler (generated by calls to icmAbortWrite in memory -// write callbacks) -// -VMI_WR_ABORT_EXCEPT_FN(armWrAbortExceptionCB) { - - armP arm = (armP)processor; - - armBusFault(arm, address, MEM_PRIV_W); -} - -// -// Validate instruction fetch from the passed address -// -static Bool validateFetchAddress( - armP arm, - Uns32 thisPC, - Uns32 snap, - Bool complete -) { - vmiProcessorP processor = (vmiProcessorP)arm; - memAccessAttrs attrs = complete ? MEM_AA_TRUE : MEM_AA_FALSE; - armVMAction action; - - if(vmirtIsExecutable(processor, thisPC)) { - - // no exception pending - return True; - - } else if((action=armVMMiss(arm, MEM_PRIV_X, thisPC, 2, attrs)) == MA_EXCEPTION) { - - // permission exception of some kind, handled by armVMMiss, so no - // further action required here. - return False; - - } else { - - // no exception pending - return True; - } -} - -// -// This is called by the simulator when fetching from an instruction address. -// It gives the model an opportunity to take an exception instead. -// -VMI_IFETCH_FN(armIFetchExceptionCB) { - - armP arm = (armP)processor; - Uns32 thisPC = (Uns32)address; - Uns32 snap = IN_THUMB_MODE(arm) ? 1 : 3; - armExceptNum exceptNum = exceptionEnabled(arm, inHandlerMode(arm)); - Bool fetchOK; - - if(exceptNum!=AEN_None) { - - // exception pending - fetchOK = False; - - if(!complete) { - - // no action - - } else if(!arm->sleepOnExit) { - - // update registers to complete exception if required - startException(arm, exceptNum, thisPC); - - } else { - - // restart after SCR.SLEEPONEXIT, taking tail-chained exception - arm->sleepOnExit = False; - - // indicate that we are entering the exception epilogue - arm->exceptionContext = AEC_PopStack; - arm->derivedException = AEN_None; - - // take tail-chained exception - takeException(arm, exceptNum); - - // indicate exception epilogue is no longer active - arm->exceptionContext = AEC_None; - } - - } else if(!IN_THUMB_MODE(arm)) { - - // unsupported ARM mode execution - fetchOK = False; - - // update registers to complete exception if required - if(complete) { - armUsageFault(arm, thisPC); - } - - } else if(!validateFetchAddress(arm, thisPC, snap, complete)) { - - // fetch exception (handled in validateFetchAddress) - fetchOK = False; - - } else if((thisPC+2) & (MIN_PAGE_SIZE-1)) { - - // simPC isn't two bytes before page end - success - fetchOK = True; - - } else if(armGetInstructionSize(arm, thisPC) == 2) { - - // instruction at simPC is a two-byte instruction - success - fetchOK = True; - - } else if(!validateFetchAddress(arm, thisPC+2, snap, complete)) { - - // fetch exception (handled in validateFetchAddress) - fetchOK = False; - - } else { - - // no exception - fetchOK = True; - } - - // return appropriate result - if(fetchOK) { - return VMI_FETCH_NONE; - } else if(complete) { - return VMI_FETCH_EXCEPTION_COMPLETE; - } else { - return VMI_FETCH_EXCEPTION_PENDING; - } -} - -// -// This is called by the simulator on a simulated arithmetic exception -// -VMI_ARITH_EXCEPT_FN(armArithExceptionCB) { - - armP arm = (armP)processor; - - if(exceptionContext==VMI_EXCEPT_CXT_CALL) { - - // not expecting any arithmetic exceptions in calls from morphed code - return VMI_NUMERIC_UNHANDLED; - - } else switch(exceptionType) { - - case VMI_INTEGER_DIVIDE_BY_ZERO: - // handle divide-by-zero - if(SCS_FIELD(arm, CCR, DIV_0_TRP)) { - SCS_FIELD(arm, CFSR, DIVBYZERO) = 1; - armUsageFault(arm, getPC(arm)); - } else { - arm->regs[arm->divideTarget] = 0; - } - return VMI_NUMERIC_ABORT; - - case VMI_INTEGER_OVERFLOW: - // handle overflow (MIN_INT / -1) - arm->regs[arm->divideTarget] = 0x80000000; - return VMI_NUMERIC_ABORT; - - default: - // not expecting any other arithmetic exception types - return VMI_NUMERIC_UNHANDLED; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// TICK TIMER -//////////////////////////////////////////////////////////////////////////////// - -// -// Return lower 32 bits of the instruction count -// -inline static Uns64 getThisICount(armP arm) { - return vmirtGetICount((vmiProcessorP)arm); -} - -// -// Is the tick timer enabled? -// -static Bool timerEnabled(armP arm) { - return ( - !arm->disableTimerRVR0 && - SCS_FIELD(arm, SYST_CSR, ENABLE) && - SCS_FIELD(arm, SYST_CSR, CLKSOURCE) - ); -} - -// -// Must the model timer be set? -// -static Bool setModelTimer(armP arm) { - return ( - timerEnabled(arm) && - ( - // must set model timer if SysTick interrupt is enabled - SCS_FIELD(arm, SYST_CSR, TICKINT) || - // must set model timer if COUNTFLAG must be set on wrap - !SCS_FIELD(arm, SYST_CSR, COUNTFLAG) || - // must set model timer if reset value will change from before - (SCS_REG_UNS32(arm, SYST_RVR) != (arm->timerModulus-1)) - ) - ); -} - -// -// Return calculated SYST_CVR register value -// -static Uns32 getSYST_CVR(armP arm) { - - if(timerEnabled(arm)) { - - Uns64 current = getThisICount(arm); - Uns32 timerModulus = arm->timerModulus; - Uns32 delta = (current-arm->timerBase) % timerModulus; - - return delta ? timerModulus-delta : 0; - - } else { - - return SCS_REG_UNS32(arm, SYST_CVR); - } -} - -// -// Set SYST_CVR register value, enabling interrupts if required -// -static void setSYST_CVR(armP arm, Uns32 SYST_CVR) { - - Uns32 SYST_RVR = SCS_REG_UNS32(arm, SYST_RVR); - - // if both SYST_CVR and SYST_RVR are zero, timer is disabled - arm->disableTimerRVR0 = !(SYST_CVR || SYST_RVR); - - if(timerEnabled(arm)) { - - // allow for reset to SYST_RVR on decrement through zero - if(!SYST_CVR) { - SYST_CVR = arm->timerModulus = SYST_RVR+1; - } - - // set base instruction count - arm->timerBase = getThisICount(arm) - arm->timerModulus + SYST_CVR; - - } else { - - // timer stopped, record current value - SCS_REG_UNS32(arm, SYST_CVR) = SYST_CVR; - } - - // set model interrupt if required - if(setModelTimer(arm)) { - - Uns32 timerDelta = SYST_CVR-1; - - // show tick timer timeout delta - if(ARM_DEBUG_EXCEPT(arm)) { - vmiPrintf( - "Tick timer expiry scheduled in %u instructions\n", - timerDelta - ); - } - - vmirtSetICountInterrupt((vmiProcessorP)arm, timerDelta); - - } else { - - vmirtClearICountInterrupt((vmiProcessorP)arm); - } -} - -// -// Read SYST_CVR register -// -Uns32 armReadSYST_CVR(armP arm) { - return getSYST_CVR(arm); -} - -// -// Write SYST_CVR register -// -void armWriteSYST_CVR(armP arm, Uns32 newValue) { - - // SYST_CSR.COUNTFLAG is cleared by a write to SYST_CVR - SCS_FIELD(arm, SYST_CSR, COUNTFLAG) = 0; - - // set new count value, accounting for pending exceptions - setSYST_CVR(arm, newValue); -} - -// -// Read SYST_CSR register -// -Uns32 armReadSYST_CSR(armP arm) { - - Uns32 oldValue = SCS_REG_UNS32(arm, SYST_CSR); - - // action only required if SYST_CSR.COUNTFLAG is set - if(SCS_FIELD(arm, SYST_CSR, COUNTFLAG)) { - - // get current value of count register prior to SYST_CSR update - Uns32 SYST_CVR = getSYST_CVR(arm); - - // SYST_CSR.COUNTFLAG is cleared by a read of SYST_CSR - SCS_FIELD(arm, SYST_CSR, COUNTFLAG) = 0; - - // restore original count value, accounting for pending exceptions - setSYST_CVR(arm, SYST_CVR); - } - - return oldValue; -} - -// -// Write SYST_CSR register -// -void armWriteSYST_CSR(armP arm, Uns32 newValue) { - - // get current value of count register prior to SYST_CSR update - Uns32 SYST_CVR = getSYST_CVR(arm); - Uns32 oldValue = SCS_REG_UNS32(arm, SYST_CSR); - - // update the register - SCS_REG_UNS32(arm, SYST_CSR) = ( - (oldValue & ~SCS_WRITE_MASK_SYST_CSR) | - (newValue & SCS_WRITE_MASK_SYST_CSR) - ); - - // restore original count value, accounting for pending exceptions - setSYST_CVR(arm, SYST_CVR); -} - -// -// Write SYST_RVR register -// -void armWriteSYST_RVR(armP arm, Uns32 newValue) { - - // mask to allowed range - newValue &= SCS_WRITE_MASK_SYST_RVR; - - // action only required if SYST_RVR has changed - if(newValue != SCS_REG_UNS32(arm, SYST_RVR)) { - - // get current value of count register prior to SYST_CSR update - Uns32 SYST_CVR = getSYST_CVR(arm); - - // update the register - SCS_REG_UNS32(arm, SYST_RVR) = newValue; - - // restore original count value, accounting for pending exceptions - setSYST_CVR(arm, SYST_CVR); - } -} - -// -// This is called when the tick timer has expired. It should set the interrupt -// pending bit for this exception. The exception is subsequently handled in the -// instruction fetch handler, armIFetchExceptionCB. -// -VMI_ICOUNT_FN(armICountPendingCB) { - - armP arm = (armP)processor; - Uns32 SYST_RVR = SCS_REG_UNS32(arm, SYST_RVR); - - // report tick timer expiry - if(ARM_DEBUG_EXCEPT(arm)) { - vmiPrintf("Tick timer expired\n"); - } - - // sanity check that the timer is enabled - VMI_ASSERT(timerEnabled(arm), "timer interrupt, but timer was disabled"); - - // indicate timer has expired - SCS_FIELD(arm, SYST_CSR, COUNTFLAG) = 1; - - // if interrupt generation is enabled, raise SysTick exception - if(SCS_FIELD(arm, SYST_CSR, TICKINT)) { - raiseNow(arm, AEN_SysTick); - } - - // this is the length of the countdown timer cycle - arm->timerModulus = SYST_RVR+1; - - // schedule the next interrupt event, including one instruction from this - // cycle - setSYST_CVR(arm, SYST_RVR ? arm->timerModulus+1 : 0); -} - - -//////////////////////////////////////////////////////////////////////////////// -// EXTERNAL INTERRUPTS -//////////////////////////////////////////////////////////////////////////////// - -// -// Called by the simulator when an external reset is raised -// -static VMI_NET_CHANGE_FN(externalReset) { - raiseNow((armP)processor, AEN_Reset); -} - -// -// Called by the simulator when an external reset is raised -// -static VMI_NET_CHANGE_FN(externalNMI) { - raiseNow((armP)processor, AEN_NMI); -} - - -static void externalInterrupt(armP arm, Uns32 intNum, Bool raise) { - - armExceptNum exceptNum = intNum+16; - - if(intNum>=NUM_INTERRUPTS(arm)) { - - // interrupt out of range - vmiMessage("W", CPU_PREFIX "NET", - "ARM external interrupt ID is %u but must be 0..%u - ignored", - intNum, NUM_INTERRUPTS(arm)-1 - ); - - } else if(raise) { - - // interrupt being raised - raiseNow(arm, exceptNum); - - } else { - - // interrupt being lowered - lower(arm, exceptNum); - } -} - -// -// Called by the simulator when an external scalar interrupt is raised. -// In this model the net value is either zero (low) or non-zero (high) -// - -static VMI_NET_CHANGE_FN(externalScalarInterrupt) { - - armP arm = (armP)processor; - UnsPS intNum = (UnsPS)userData; - - externalInterrupt(arm, intNum, newValue); -} - -// -// Called by the simulator when an external vector interrupt is raised. -// In this model the value encodes the interrupt number in bits 31-1, -// and the level in bit0. The model ignores an interrupt number if too big. -// -static VMI_NET_CHANGE_FN(externalVectorInterrupt) { - - armP arm = (armP)processor; - Uns32 intNum = (newValue>>1); - Bool raise = newValue&1; - - externalInterrupt(arm, intNum, raise); -} - -// -// Called by the simulator when an external memory prefetch abort is raised -// -static VMI_NET_CHANGE_FN(externalPAbort) { - armBusFault((armP)processor, 0, MEM_PRIV_X); -} - -// -// Called by the simulator when an external memory data abort is raised -// -static VMI_NET_CHANGE_FN(externalDAbort) { - // TODO : newValue needs to be the (data) address that failed - armBusFault((armP)processor, newValue, MEM_PRIV_RW); -} - -// -// Called by the simulator when an external event is raised -// -static VMI_NET_CHANGE_FN(externalEvent) { - setEventRegister((armP)processor); -} - -// -// Raise an exception -// -void armRaise(armP arm, armExceptNum num) { - raiseNow(arm, num); -} - -// -// Perform SEV instruction actions -// -void armSEV(armP arm) { - writeNet(arm, arm->eventOut, 1); -} - - -//////////////////////////////////////////////////////////////////////////////// -// NET PORTS -//////////////////////////////////////////////////////////////////////////////// - -// -// Return number of members of an array -// -#define NUM_MEMBERS(_A) (sizeof(_A)/sizeof((_A)[0])) - -// -// Create port specifications -// -void armNewPortSpecs(armP arm) { - - // declare template port structure for fixed ports - vmiNetPort template[] = { - - // output ports - {"sysResetReq",vmi_NP_OUTPUT, (void*)0, 0, &arm->sysResetReq }, - {"intISS", vmi_NP_OUTPUT, (void*)0, 0, &arm->intISS }, - {"eventOut", vmi_NP_OUTPUT, (void*)0, 0, &arm->eventOut }, - {"lockup", vmi_NP_OUTPUT, (void*)0, 0, &arm->lockup }, - - // input ports - {"int", vmi_NP_INPUT, (void*)2, externalVectorInterrupt }, - {"reset", vmi_NP_INPUT, (void*)0, externalReset }, - {"nmi", vmi_NP_INPUT, (void*)0, externalNMI }, - {"pabort", vmi_NP_INPUT, (void*)0, externalPAbort }, - {"dabort", vmi_NP_INPUT, (void*)0, externalDAbort }, - {"eventIn", vmi_NP_INPUT, (void*)0, externalEvent }, - }; - - // calculate number of members - Uns32 numFixed = NUM_MEMBERS(template); - Uns32 numInterrupts = NUM_INTERRUPTS(arm); - Uns32 i; - - // allocate permanent port structure (including terminator) - vmiNetPortP result = STYPE_CALLOC_N(vmiNetPort, numFixed+numInterrupts+1); - - // fill fixed members, replacing names with an allocated copy - for(i=0; iname = strdup(netName); - this->type = vmi_NP_INPUT; - this->userData = (void*)(UnsPS)i; - this->netChangeCB = externalScalarInterrupt; - } - - // save ports on processor - arm->netPorts = result; -} - -// -// Free net port list -// -void armFreePortSpecs(armP arm) { - - Uns32 i; - - for(i=0; arm->netPorts[i].name; i++) { - STYPE_FREE(arm->netPorts[i].name); - } - - STYPE_FREE(arm->netPorts); -} - -// -// Get the next net port -// -VMI_NET_PORT_SPECS_FN(armGetNetPortSpec) { - - armP arm = (armP)processor; - vmiNetPortP this; - - if(!prev) { - this = arm->netPorts; - } else { - this = prev + 1; - } - - return this->name ? this : 0; -} - - -//////////////////////////////////////////////////////////////////////////////// -// FLOATING POINT SUPPORT -//////////////////////////////////////////////////////////////////////////////// - -// -// This is the ARM PreserveFPState primitive -// -void armPreserveFPState(armP arm) { - -// TODO: accesses need to be done at priv level indicated by FPCCR -// Bool isPriv = SCS_FIELD(arm, FPCCR, USER) == 0; - Uns32 fpFramePtr = SCS_REG_UNS32(arm, FPCAR); - memDomainP domain = arm->FPCARdomain; - - // Sanity checks - VMI_ASSERT(domain!=0, "FPCAR memory domain is NULL"); - VMI_ASSERT(SCS_FIELD(arm, FPCCR, LSPACT), "FPCCR.LSPACT not active"); - - // Clear FPCRdomain since it cannot be used again until LSPACT is set, - // and it will be reset at that time - arm->FPCARdomain = 0; - - // TODO: exceptions occurring during this routine need special handling - // For now just do an assertion if an exception occurs at this point - armExceptCxt oldContext = arm->exceptionContext; - arm->exceptionContext = AEC_PreserveFPState; - - // Push the floating point state onto the space allocated on the stack for it - pushFP(arm, fpFramePtr, domain); - - // Turn off the LSPACT flag - armUpdateLSPACT(arm, 0); - - // restore previous context - arm->exceptionContext = oldContext; - -} diff --git a/simulators/ovp/armmModel/armmMain.c b/simulators/ovp/armmModel/armmMain.c deleted file mode 100644 index 5fc8da5e..00000000 --- a/simulators/ovp/armmModel/armmMain.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// standard header files -#include - -// VMI header files -#include "vmi/vmiAttrs.h" -#include "vmi/vmiCommand.h" -#include "vmi/vmiMessage.h" -#include "vmi/vmiRt.h" - -// model header files -#include "armConfig.h" -#include "armDecode.h" -#include "armDebug.h" -#include "armmDoc.h" -#include "armExceptions.h" -#include "armFunctions.h" -#include "armMode.h" -#include "armmParameters.h" -#include "armStructure.h" -#include "armSys.h" -#include "armSysRegisters.h" -#include "armUtils.h" -#include "armVM.h" -#include "armVFP.h" - -#include -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_MAIN" - -//////////////////////////////////////////////////////////////////////////////// -// PARSING CONFIGURATION OPTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Return processor configuration variant argument -// -static armConfigCP getConfigVariantArg(armP arm, armParamValuesP params) { - - armConfigCP match; - - if(params->SETBIT(variant)) { - - match = &armConfigTable[params->variant]; - - } else { - - match = armConfigTable; - - if(arm->verbose) { - - // report the value specified for an option in verbose mode - vmiMessage("I", CPU_PREFIX"_ANS1", - "Attribute '%s' not specified; defaulting to '%s'", - "variant", - match->name - ); - } - } - - // return matching configuration - return match; -} - -//////////////////////////////////////////////////////////////////////////////// -// CONSTRUCTOR AND DESTRUCTOR -//////////////////////////////////////////////////////////////////////////////// - -// specify default value for entire system register -#define SET_SCS_REG_DEFAULT(_R, _V) \ - union {Uns32 u32; SCS_REG_DECL(_R);} _U = {_V}; \ - SCS_REG_STRUCT_DEFAULT(arm, _R) = _U._R - -// -// Initialize processor exclusiveTagMask -// -static void setExclusiveTagMask(armP arm) { - arm->exclusiveTagMask = (-1 << (arm->configInfo.ERG+2)); -} - -void failSALset(unsigned int pointer); -// -// ARM processor constructor -// -VMI_CONSTRUCTOR_FN(armConstructor) { - - armP arm = (armP)processor; - armParamValuesP params = (armParamValuesP)parameterValues; - - - // initialize exclusive tag - arm->exclusiveTag = ARM_NO_TAG; - - // save flags on processor structure - arm->flags = vmirtProcessorFlags(processor); - - unsigned int failp = params->fail_salp; - failSALset(failp); - - - // get string configuration options - arm->simEx = simulateExceptions; - arm->verbose = params->verbose; - arm->compatMode = params->compatibility; - arm->showHiddenRegs = params->showHiddenRegs; - arm->UAL = params->UAL; - arm->disableBitBand = params->disableBitBand; - - // get default variant information - arm->configInfo = *getConfigVariantArg(arm, params); - - // override data endianness - armSetInitialEndian(arm, params->endian); - - // override instruction endianness - arm->instructionEndian = params->instructionEndian; - - // override other configuration values - if(params->SETBIT(override_debugMask)) { - arm->flags = params->override_debugMask; - } - if(params->SETBIT(override_CPUID)) { - SET_SCS_REG_DEFAULT(CPUID, params->override_CPUID); - } - if(params->SETBIT(override_MPU_TYPE)) { - SET_SCS_REG_DEFAULT(MPU_TYPE, params->override_MPU_TYPE); - } - if(params->SETBIT(override_InstructionAttributes0)) { - SET_SCS_REG_DEFAULT(ID_ISAR0, params->override_InstructionAttributes0); - } - if(params->SETBIT(override_InstructionAttributes1)) { - SET_SCS_REG_DEFAULT(ID_ISAR1, params->override_InstructionAttributes1); - } - if(params->SETBIT(override_InstructionAttributes2)) { - SET_SCS_REG_DEFAULT(ID_ISAR2, params->override_InstructionAttributes2); - } - if(params->SETBIT(override_InstructionAttributes3)) { - SET_SCS_REG_DEFAULT(ID_ISAR3, params->override_InstructionAttributes3); - } - if(params->SETBIT(override_InstructionAttributes4)) { - SET_SCS_REG_DEFAULT(ID_ISAR4, params->override_InstructionAttributes4); - } - if(params->SETBIT(override_InstructionAttributes5)) { - SET_SCS_REG_DEFAULT(ID_ISAR5, params->override_InstructionAttributes5); - } - if(params->SETBIT(override_MVFR0)) { - SET_SCS_REG_DEFAULT(MVFR0, params->override_MVFR0); - } - if(params->SETBIT(override_MVFR1)) { - SET_SCS_REG_DEFAULT(MVFR1, params->override_MVFR1); - } - if(params->SETBIT(override_rotateUnaligned)) { - arm->configInfo.rotateUnaligned = params->override_rotateUnaligned; - } - if(params->SETBIT(override_align64as32)) { - arm->configInfo.align64as32 = params->override_align64as32; - } - if(params->SETBIT(override_STRoffsetPC12)) { - arm->configInfo.STRoffsetPC12 = params->override_STRoffsetPC12; - } - if(params->SETBIT(override_ERG)) { - arm->configInfo.ERG = params->override_ERG; - } - if(params->SETBIT(override_priorityBits)) { - arm->configInfo.priorityBitsM1 = params->override_priorityBits-1; - } - if(params->SETBIT(override_numInterrupts)) { - NUM_INTERRUPTS(arm) = params->override_numInterrupts; - } - - // set read-only registers to their initial state (AFTER applying overrides) - armSysInitialize(arm); - - // register view objects and event handlers (AFTER armSysInitialize) - vmiViewObjectP viewObject = vmirtGetProcessorViewObject(processor); - armAddSysRegistersView(arm, viewObject); - - // Initialize FPU if present - armFPInitialize(arm); - - // Check for user enable of VFP instructions at reset? - if (params->SETBIT(enableVFPAtReset) && params->enableVFPAtReset) { - SCS_FIELD_DEFAULT(arm, CPACR, cp10) = 3; - SCS_FIELD_DEFAULT(arm, CPACR, cp11) = 3; - } - - // initialize exclusiveTagMask - setExclusiveTagMask(arm); - - // initialize priority mask - Uns32 priorityBits = PRIORITY_BITS(arm); - arm->priorityMask = ((1<priorityMask |= arm->priorityMask << 8; - arm->priorityMask |= arm->priorityMask << 16; - - // ensure number of external interrupts is in bounds - if(NUM_INTERRUPTS(arm)>ARM_INTERRUPT_NUM) { - NUM_INTERRUPTS(arm) = ARM_INTERRUPT_NUM; - } - - // initialize exception mask number and top mask - arm->exceptNum = NUM_INTERRUPTS(arm) + AEN_ExternalInt0; - arm->exceptMaskNum = (arm->exceptNum+31)/32; - - // indicate reset exception is pending; otherwise, force into Thumb mode - // (default is ARM mode) - if(!ARM_DISASSEMBLE(arm) && params->resetAtTime0) { - armRaise(arm, AEN_Reset); - } else { - IN_THUMB_MODE(arm) = 1; - } - - // reset stack pointer (and banked variants) in gdb compatibility mode - if(arm->compatMode==COMPAT_GDB) { - arm->regs[ARM_REG_SP] = 0x800; - arm->bank.R13_process = 0x800; - } - - // force into thumb mode if required - if(ARM_THUMB(arm)) { - IN_THUMB_MODE(arm) = 1; - } - - // set callbacks (for intercept libraries) - arm->decoderCB = armDecode; - arm->isizeCB = armGetInstructionSizeMode; - - // create port specifications - armNewPortSpecs(arm); - - // install documentation - armmDoc(processor, parameterValues); -} - -// -// ARM processor destructor -// -VMI_DESTRUCTOR_FN(armDestructor) { - - armP arm = (armP)processor; - - // free port specifications - armFreePortSpecs(arm); - - // free virtual memory structures - armVMFree(arm); -} - - diff --git a/simulators/ovp/armmModel/armmMorphFunctions.c b/simulators/ovp/armmModel/armmMorphFunctions.c deleted file mode 100644 index 44dcae38..00000000 --- a/simulators/ovp/armmModel/armmMorphFunctions.c +++ /dev/null @@ -1,5141 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiMessage.h" - -// model header files -#include "armConfig.h" -#include "armDecode.h" -#include "armEmit.h" -#include "armExceptions.h" -#include "armFunctions.h" -#include "armMessage.h" -#include "armMorph.h" -#include "armMorphFunctions.h" -#include "armRegisters.h" -#include "armStructure.h" -#include "armUtils.h" -#include "armVariant.h" -#include "armVM.h" -#include "armVFP.h" - - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_MORPH" - - -//////////////////////////////////////////////////////////////////////////////// -// EXCEPTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Generic exception callback -// -#define EXCEPTION_FN(_NAME) void _NAME(armP arm, Uns32 thisPC) -typedef EXCEPTION_FN((*exceptionFn)); - -// -// Emit call to exception function -// -static void emitExceptionCall(armMorphStateP state, exceptionFn cb) { - - Uns32 bits = ARM_GPR_BITS; - - // emit processor argument - armEmitArgProcessor(state); - armEmitArgSimPC(state, bits); - armEmitCall(state, (vmiCallFn)cb); - - // terminate the current block - armEmitEndBlock(); -} - - -//////////////////////////////////////////////////////////////////////////////// -// UNIMPLEMENTED/UNDEFINED INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Called for an unimplemented instruction -// -static void unimplemented(armP arm, Uns32 thisPC) { - - vmiMessage("F", CPU_PREFIX"_UII", - SRCREF_FMT "unimplemented instruction", - SRCREF_ARGS(arm, thisPC) - ); -} - -// -// Default morpher callback for unimplemented instructions -// -static void emitUnimplemented(armMorphStateP state) { - armEmitArgProcessor(state); - armEmitArgSimPC(state, ARM_GPR_BITS); - armEmitCall(state, (vmiCallFn)unimplemented); - armEmitExit(); -} - -// -// Called for UsageFault exception -// -static void usageFault(armP arm, Uns32 thisPC) { - - vmiMessage("E", CPU_PREFIX"_UDI", - SRCREF_FMT "usage fault - enable simulated exceptions " - "to continue simulation if this behavior is desired", - SRCREF_ARGS(arm, thisPC) - ); -} - -// -// Emit code for a UsageFault exception -// -static void emitUsageFault(armMorphStateP state, Uns32 reason) { - - Uns32 bits = ARM_GPR_BITS; - - // update UFSR (CFSR) - armEmitBinopRC(state, bits, vmi_OR, ARM_SCS_REG(SCS_ID(CFSR)), reason, 0); - - // handle UsageFault - if(state->arm->simEx) { - emitExceptionCall(state, armUsageFault); - } else { - armEmitArgProcessor(state); - armEmitArgSimPC(state, bits); - armEmitCall(state, (vmiCallFn)usageFault); - armEmitExit(); - } -} - -// -// Called for an instruction that isn't supported on this variant -// -static void notVariantMessage(armP arm, Uns32 thisPC) { - - vmiMessage("W", CPU_PREFIX"_NSV", - SRCREF_FMT "not supported on this variant", - SRCREF_ARGS(arm, thisPC) - ); -} - -// -// Morpher callback for instructions that are not valid on this processor -// variant -// -static ARM_MORPH_FN(emitNotVariant) { - - // report the offending instruction in verbose mode - if(state->arm->verbose) { - armEmitArgProcessor(state); - armEmitArgSimPC(state, ARM_GPR_BITS); - armEmitCall(state, (vmiCallFn)notVariantMessage); - } - - // take UsageFault exception - emitUsageFault(state, EXC_UNDEF_UNDEFINSTR); -} - -// -// Called for an undefined coprocessor instruction -// -static void undefinedCPMessage(armP arm, Uns32 thisPC) { - - vmiMessage("a", CPU_PREFIX"_UCA", - SRCREF_FMT "unsupported coprocessor access", - SRCREF_ARGS(arm, thisPC) - ); -} - - -//////////////////////////////////////////////////////////////////////////////// -// FLAGS -//////////////////////////////////////////////////////////////////////////////// - -const static vmiFlags flagsCIn = { - ARM_CF_CONST, - { - [vmi_CF] = VMI_NOFLAG_CONST, - [vmi_PF] = VMI_NOFLAG_CONST, - [vmi_ZF] = VMI_NOFLAG_CONST, - [vmi_SF] = VMI_NOFLAG_CONST, - [vmi_OF] = VMI_NOFLAG_CONST - } -}; - -const static vmiFlags flagsCOut = { - ARM_CF_CONST, - { - [vmi_CF] = ARM_CF_CONST, - [vmi_PF] = VMI_NOFLAG_CONST, - [vmi_ZF] = VMI_NOFLAG_CONST, - [vmi_SF] = VMI_NOFLAG_CONST, - [vmi_OF] = VMI_NOFLAG_CONST - } -}; - -// Macro accessors for flags -#define FLAGS_CIN &flagsCIn -#define FLAGS_COUT &flagsCOut - -// -// Return condition flags associated with an instruction, or null if no flags -// are applicable -// -static vmiFlagsCP getFlagsOrNull(armMorphStateP state) { - return state->info.f ? state->attrs->flagsRW : 0; -} - -// -// Return condition flags associated with an instruction, or FLAGS_CIN if no -// flags are applicable -// -static vmiFlagsCP getFlagsOrCIn(armMorphStateP state, vmiReg rd) { - if(!state->info.f) { - return state->attrs->flagsR; - } else if(!VMI_REG_EQUAL(rd, ARM_PC)) { - return state->attrs->flagsRW; - } else { - return state->attrs->flagsR; - } -} - -// -// If the instruction sets flags from the shifter output, return FLAGS_COUT -// -static vmiFlagsCP getShifterCOut(armMorphStateP state, vmiReg rd) { - if(!state->info.f) { - return FLAGS_CIN; - } else if(!state->attrs->shiftCOut) { - return FLAGS_CIN; - } else if(!VMI_REG_EQUAL(rd, ARM_PC)) { - return FLAGS_COUT; - } else { - return FLAGS_CIN; - } -} - -// -// Do the flags specify that the shifter sets the carry out? -// -inline static Bool shifterSetsCOut(vmiFlagsCP flags) { - return (flags==FLAGS_COUT); -} - -//////////////////////////////////////////////////////////////////////////////// -// REGISTER ACCESS UTILITIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Register access macros -// -#define GET_RD(_S, _R) getRD(_S, _S->info._R) -#define GET_RS(_S, _R) getRS(_S, _S->info._R) - -// VFP register access macros -#define GET_VFP_REG(_S, _R, _SZ) getVFPReg((_S), (_S)->info._R, (_SZ)) -#define GET_VFP_SREG(_S, _R) getVFPReg((_S), (_S)->info._R, 4) -#define GET_VFP_DREG(_S, _R) getVFPReg((_S), (_S)->info._R, 8) -#define GET_VFP_SCALAR(_S, _R, _IDX) getVFPReg((_S), (2*((_S)->info._R))+(_IDX), 4) - -// -// Return vmiReg for GPR with the passed index -// NOTE: PC is a temporary, others are true registers -// -static vmiReg getGPR(armMorphStateP state, Uns32 index) { - return index==ARM_REG_PC ? ARM_PC : ARM_REG(index); -} - -// -// Return vmiReg for target GPR with the passed index -// -static vmiReg getRD(armMorphStateP state, Uns32 index) { - return getGPR(state, index); -} - -// -// Return vmiReg for source GPR with the passed index -// -static vmiReg getRS(armMorphStateP state, Uns32 index) { - - vmiReg r = getGPR(state, index); - - // ensure PC is created on demand if required - if(VMI_REG_EQUAL(r, ARM_PC)) { - armEmitGetPC(state); - } - - return r; -} - -// -// Return vmiReg object for low half of 32-bit register -// -inline static vmiReg getR32Lo(vmiReg reg32) { - return reg32; -} - -// -// Return vmiReg object for high half of 32-bit register -// -inline static vmiReg getR32Hi(vmiReg reg32) { - return VMI_REG_DELTA(reg32, sizeof(Uns16)); -} - -// -// Return vmiReg object for low half of 64-bit register -// -inline static vmiReg getR64Lo(vmiReg reg64) { - return reg64; -} - -// -// Return vmiReg object for high half of 64-bit register -// -inline static vmiReg getR64Hi(vmiReg reg64) { - return VMI_REG_DELTA(reg64, sizeof(Uns32)); -} - -// -// Return vmiReg for VFP register, addressed as a Single or Double precision -// -static vmiReg getVFPReg(armMorphStateP state, Uns32 regNum, Uns32 ebytes) { - - VMI_ASSERT(ebytes==2 || ebytes==4 || ebytes == 8, "Invalid VFP ebytes %d", ebytes); - - armP arm = state->arm; - vmiReg reg = VMI_NOREG; - Uns32 vfpRegisters = SCS_FIELD(arm, MVFR0, A_SIMD_Registers); - Uns32 numRegs = (vfpRegisters == 1) ? ARM_VFP16_REG_NUM : ARM_VFP32_REG_NUM; - - - if(!vfpRegisters) { - - // VFP Registers are not present - emitUsageFault(state, EXC_UNDEF_UNDEFINSTR); - - } else if((regNum*ebytes) >= (numRegs*ARM_VFP_REG_BYTES)) { - - // Register number is out of range of the implemented number of registers - emitUsageFault(state, EXC_UNDEF_UNDEFINSTR); - - } else { - - // get the indicated register - switch (ebytes) { - case 1: reg = ARM_BREG(regNum); break; - case 2: reg = ARM_HREG(regNum); break; - case 4: reg = ARM_WREG(regNum); break; - case 8: reg = ARM_DREG(regNum); break; - default: VMI_ABORT("Invalid ebytes %d", ebytes); - } - } - - return reg; -} - - -//////////////////////////////////////////////////////////////////////////////// -// INSTRUCTION SKIPPING UTILITIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Save the skip label on the info structure -// -inline static void setSkipLabel(armMorphStateP state, vmiLabelP label) { - state->skipLabel = label; -} - -// -// Return the skip label on the info structure -// -inline static vmiLabelP getSkipLabel(armMorphStateP state) { - return state->skipLabel; -} - -// -// Insert a label -// -inline static void emitLabel(vmiLabelP label) { - - if(label) { - armEmitInsertLabel(label); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// MISCELLANEOUS UTILITIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Return the version of the instruction set implemented by the processor -// -inline static Uns32 getInstructionVersion(armP arm) { - return ARM_INSTRUCTION_VERSION(arm->configInfo.arch); -} - -// -// Return the constant value adjusted so that when added to the PC the result -// is always word aligned -// -inline static Uns32 alignConstWithPC(armMorphStateP state, Uns32 c) { - return c - (state->info.thisPC & 2); -} - - -//////////////////////////////////////////////////////////////////////////////// -// TEMPORARIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Get the current active temporary -// -inline static vmiReg getTemp(armMorphStateP state) { - VMI_ASSERT(state->tempIdxtempIdx); -} - -// -// Allocate a new 32-bit temporary -// -inline static vmiReg newTemp32(armMorphStateP state) { - vmiReg temp = getTemp(state); - state->tempIdx++; - return temp; -} - -// -// Free a 32-bit temporary -// -inline static void freeTemp32(armMorphStateP state) { - VMI_ASSERT(state->tempIdx, "%s: temporary overflow", FUNC_NAME); - state->tempIdx--; -} - -// -// Allocate a new 64-bit temporary -// -inline static vmiReg newTemp64(armMorphStateP state) { - vmiReg temp = newTemp32(state); newTemp32(state); - return temp; -} - -// -// Free a 64-bit temporary -// -inline static void freeTemp64(armMorphStateP state) { - freeTemp32(state); freeTemp32(state); -} - -// -// Allocate a new 128-bit temporary -// -inline static vmiReg newTemp128(armMorphStateP state) { - vmiReg temp = newTemp64(state); newTemp64(state); - return temp; -} - -// -// Free a 128-bit temporary -// -inline static void freeTemp128(armMorphStateP state) { - freeTemp64(state); freeTemp64(state); -} - -//////////////////////////////////////////////////////////////////////////////// -// TEMPORARY FLAGS -//////////////////////////////////////////////////////////////////////////////// - -// -// Return vmiFlags generating sign and overflow in temporary -// -static vmiFlags getSFOFFlags(vmiReg tf) { - - vmiFlags flags = VMI_NOFLAGS; - - // define overflow and sign flags - vmiReg of = tf; - vmiReg sf = VMI_REG_DELTA(of, 1); - - // define vmiFlags structure using the overflow and sign flags - flags.f[vmi_SF] = sf; - flags.f[vmi_OF] = of; - - // return vmiFlags structure - return flags; -} - -// -// Return vmiFlags generating overflow in temporary -// -static vmiFlags getOFFlags(vmiReg tf) { - - vmiFlags flags = VMI_NOFLAGS; - - // define vmiFlags structure using the overflow flag - flags.f[vmi_OF] = tf; - - // return vmiFlags structure - return flags; -} - -// -// Return vmiFlags generating zero flag in temporary -// -static vmiFlags getZFFlags(vmiReg tf) { - - vmiFlags flags = VMI_NOFLAGS; - - // define vmiFlags structure using the carry flag - flags.f[vmi_ZF] = tf; - - // return vmiFlags structure - return flags; -} - -// -// Return vmiFlags generating and using carry in temporary -// -static vmiFlags getCFFlags(vmiReg tf) { - - vmiFlags flags = VMI_NOFLAGS; - - // define vmiFlags structure using the carry flag - flags.cin = tf; - flags.f[vmi_CF] = tf; - - // return vmiFlags structure - return flags; -} - -//////////////////////////////////////////////////////////////////////////////// -// CONDITIONAL INSTRUCTION EXECUTION -//////////////////////////////////////////////////////////////////////////////// - -// -// For conditions, this enumeration describes the circumstances under which the -// condition is satisfied -// -typedef enum armCondOpE { - ACO_ALWAYS = 0, // condition always True - ACO_FALSE = 1, // condition satisfied if flag unset - ACO_TRUE = 2, // condition satisfied if flag set -} armCondOp; - -// -// For conditions, this structure describes a flag and a value for a match -// -typedef struct armCondS { - vmiReg flag; - armCondOp op; -} armCond, *armCondP; - -// -// Emit code to prepare a conditional operation and return an armCond structure -// giving the offset of a flag to compare against -// -static armCond emitPrepareCondition(armMorphStateP state) { - - const static armCond condTable[ARM_C_LAST] = { - [ARM_C_EQ] = {ARM_ZF_CONST, ACO_TRUE }, // ZF==1 - [ARM_C_NE] = {ARM_ZF_CONST, ACO_FALSE }, // ZF==0 - [ARM_C_CS] = {ARM_CF_CONST, ACO_TRUE }, // CF==1 - [ARM_C_CC] = {ARM_CF_CONST, ACO_FALSE }, // CF==0 - [ARM_C_MI] = {ARM_NF_CONST, ACO_TRUE }, // NF==1 - [ARM_C_PL] = {ARM_NF_CONST, ACO_FALSE }, // NF==0 - [ARM_C_VS] = {ARM_VF_CONST, ACO_TRUE }, // VF==1 - [ARM_C_VC] = {ARM_VF_CONST, ACO_FALSE }, // VF==0 - [ARM_C_HI] = {ARM_HI_CONST, ACO_TRUE }, // (CF==1) && (ZF==0) - [ARM_C_LS] = {ARM_HI_CONST, ACO_FALSE }, // (CF==0) || (ZF==1) - [ARM_C_GE] = {ARM_LT_CONST, ACO_FALSE }, // NF==VF - [ARM_C_LT] = {ARM_LT_CONST, ACO_TRUE }, // NF!=VF - [ARM_C_GT] = {ARM_LE_CONST, ACO_FALSE }, // (ZF==0) && (NF==VF) - [ARM_C_LE] = {ARM_LE_CONST, ACO_TRUE }, // (ZF==1) || (NF!=VF) - [ARM_C_AL] = {VMI_NOREG, ACO_ALWAYS}, // always - [ARM_C_NV] = {VMI_NOREG, ACO_ALWAYS} // always (historically never) - }; - - // get the table entry corresponding to the instruction condition - armCond cond = condTable[state->info.cond]; - vmiReg tf = cond.flag; - armP arm = state->arm; - - switch(state->info.cond) { - - case ARM_C_AL: - case ARM_C_NV: - // unconditional execution - break; - - case ARM_C_EQ: - case ARM_C_NE: - case ARM_C_CS: - case ARM_C_CC: - case ARM_C_MI: - case ARM_C_PL: - case ARM_C_VS: - case ARM_C_VC: - // basic flags, always valid - break; - - case ARM_C_GT: // (ZF==0) && (NF==VF) - case ARM_C_LE: // (ZF==1) || (NF!=VF) - // derived LE flag - if(!arm->validLE) { - arm->validLE = True; - armEmitBinopRRR(state, 8, vmi_XOR, tf, ARM_NF, ARM_VF, 0); - armEmitBinopRR(state, 8, vmi_OR, tf, ARM_ZF, 0); - } - break; - - case ARM_C_GE: // NF==VF - case ARM_C_LT: // NF!=VF - // derived LT flag - if(!arm->validLT) { - arm->validLT = True; - armEmitBinopRRR(state, 8, vmi_XOR, tf, ARM_NF, ARM_VF, 0); - } - break; - - case ARM_C_HI: // (CF==1) && (ZF==0) - case ARM_C_LS: // (CF==0) || (ZF==1) - // derived HI flag - if(!arm->validHI) { - arm->validHI = True; - armEmitBinopRRR(state, 8, vmi_ANDN, tf, ARM_CF, ARM_ZF, 0); - } - break; - - default: - // not reached - VMI_ABORT("%s: unimplemented condition", FUNC_NAME); - } - - // return the condition description - return cond; -} - -// -// Create code to jump to a new label if the instruction is conditional -// -static vmiLabelP emitStartSkip(armMorphStateP state) { - - armCond cond = emitPrepareCondition(state); - vmiLabelP doSkip = 0; - - if(cond.op!=ACO_ALWAYS) { - doSkip = armEmitNewLabel(); - armEmitCondJumpLabel(cond.flag, cond.op==ACO_FALSE, doSkip); - } - - return doSkip; -} - -// -// Force all derived flag values to be regenerated -// -static void resetDerivedFlags(armMorphStateP state) { - - armP arm = state->arm; - - arm->validHI = False; - arm->validLT = False; - arm->validLE = False; -} - - -//////////////////////////////////////////////////////////////////////////////// -// ARGUMENT GENERATION -//////////////////////////////////////////////////////////////////////////////// - -// -// Map from armShiftOp to vmiBinop -// -static vmiBinop mapShiftOp(armShiftOp so) { - switch(so) { - case ARM_SO_LSL: return vmi_SHL; - case ARM_SO_LSR: return vmi_SHR; - case ARM_SO_ASR: return vmi_SAR; - case ARM_SO_ROR: return vmi_ROR; - default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); return 0; - } -} - -// -// Generate register argument by shifting register 'ra' by constant, placing -// result in register 't' -// -static void getShiftedRC( - armMorphStateP state, - vmiReg t, - vmiReg ra, - vmiFlagsCP shiftCOut -) { - Uns32 shift = state->info.c; - vmiBinop op = mapShiftOp(state->info.so); - - armEmitBinopRRC(state, ARM_GPR_BITS, op, t, ra, shift, shiftCOut); -} - -// -// Generate register argument by shifting register 'ra' by register 'rs', -// placing result in register 't' -// -static void getShiftedRR( - armMorphStateP state, - vmiReg t, - vmiReg ra, - vmiReg rs, - vmiFlagsCP shiftCOut -) { - vmiBinop op = mapShiftOp(state->info.so); - - armEmitSetShiftMask(); - armEmitBinopRRR(state, ARM_GPR_BITS, op, t, ra, rs, shiftCOut); -} - -// -// Generate register argument by rotate right of register 'ra' through carry -// -static void getExtendedR( - armMorphStateP state, - vmiReg t, - vmiReg ra, - vmiFlagsCP shiftCOut -) { - armEmitBinopRRC(state, ARM_GPR_BITS, vmi_RCR, t, ra, 1, shiftCOut); -} - - -//////////////////////////////////////////////////////////////////////////////// -// UNOPS -//////////////////////////////////////////////////////////////////////////////// - -#define vmiFlagsCPU vmiFlagsCP __attribute__ ((unused)) - -// -// Macro for emission of declarations for generic unop -// -#define EMIT_UNOP_DECLS(_S) \ - vmiReg rd = GET_RD(_S, r1); \ - vmiUnop op = _S->attrs->unop; \ - vmiFlagsCP opFlags = getFlagsOrCIn(_S, rd); \ - vmiFlagsCPU shiftCOut = getShifterCOut(_S, rd) - -// -// Macro for emission of call implementing generic unop -// -#define EMIT_UNOP_CALL(_S, _F, _S1) \ - _F(_S, ARM_GPR_BITS, op, rd, _S1, opFlags) - -// -// Macro for emission of generic unop with unshifted argument -// -#define EMIT_UNOP_NO_SHIFT(_S, _F, _S1) \ - EMIT_UNOP_DECLS(_S); \ - EMIT_UNOP_CALL(_S, _F, _S1) - -// -// Macro for emission of generic unop with shifted argument -// -#define EMIT_UNOP_SHIFT(_S, _T) \ - EMIT_UNOP_DECLS(_S); \ - _T; \ - EMIT_UNOP_CALL(_S, armEmitUnopRR, rd); - -// -// Unop with immediate -// -ARM_MORPH_FN(armEmitUnopI) { - - Uns32 c = state->info.c; - - // emit register/constant unop with unshifted argument - EMIT_UNOP_NO_SHIFT(state, armEmitUnopRC, c); - - // set carry from bit 31 of rotated constant if constant rotation was - // non-zero - if(shifterSetsCOut(shiftCOut) && state->info.crotate) { - armEmitMoveRC(state, 8, ARM_CF, (c & 0x80000000) ? 1 : 0); - } -} - -// -// Unop with register -// -ARM_MORPH_FN(armEmitUnopR) { - EMIT_UNOP_NO_SHIFT(state, armEmitUnopRR, GET_RS(state, r2)); -} - -// -// Unop with register shifted by immediate addressing mode -// -ARM_MORPH_FN(armEmitUnopRSI) { - EMIT_UNOP_SHIFT( - state, - getShiftedRC(state, rd, GET_RS(state, r2), shiftCOut) - ); -} - -// -// Unop with register shifted by register addressing mode -// -ARM_MORPH_FN(armEmitUnopRSR) { - EMIT_UNOP_SHIFT( - state, - getShiftedRR(state, rd, GET_RS(state, r2), GET_RS(state, r3), shiftCOut) - ); -} - -// -// Unop with register shifted by register addressing mode (Thumb variant) -// -ARM_MORPH_FN(armEmitUnopRSRT) { - EMIT_UNOP_SHIFT( - state, - getShiftedRR(state, rd, GET_RS(state, r1), GET_RS(state, r2), shiftCOut) - ); -} - -// -// Unop with rotate right with extend addressing mode -// -ARM_MORPH_FN(armEmitUnopRX) { - EMIT_UNOP_SHIFT( - state, - getExtendedR(state, rd, GET_RS(state, r2), shiftCOut) - ); -} - - -//////////////////////////////////////////////////////////////////////////////// -// BINOPS -//////////////////////////////////////////////////////////////////////////////// - -// -// Macro for emission of declarations for generic binop -// -#define EMIT_BINOP_DECLS(_S, _S1) \ - vmiReg rd = GET_RD(_S, r1); \ - vmiReg rs1 = GET_RS(_S, _S1); \ - vmiBinop op = _S->attrs->binop; \ - vmiFlagsCP opFlags = getFlagsOrCIn(_S, rd); \ - vmiFlagsCPU shiftCOut = getShifterCOut(_S, rd) - -// -// Macro for emission of call implementing generic binop -// -#define EMIT_BINOP_CALL(_S, _F, _S2) \ - _F(_S, ARM_GPR_BITS, op, rd, rs1, _S2, opFlags) - -// -// Macro for emission of generic binop with unshifted argument -// -#define EMIT_BINOP_NO_SHIFT(_S, _F, _S1, _S2) \ - EMIT_BINOP_DECLS(_S, _S1); \ - EMIT_BINOP_CALL(_S, _F, _S2) - -// -// Macro for emission of generic binop with shifted argument -// -#define EMIT_BINOP_SHIFT(_S, _S1, _RS2, _T) \ - EMIT_BINOP_DECLS(_S, _S1); \ - vmiReg _RS2 = newTemp32(_S); \ - _T; \ - EMIT_BINOP_CALL(_S, armEmitBinopRRR, _RS2); \ - freeTemp32(_S) - -// -// Binop with immediate -// -ARM_MORPH_FN(armEmitBinopI) { - - Uns32 c = state->info.c; - - // emit register/constant binop with unshifted argument - EMIT_BINOP_NO_SHIFT(state, armEmitBinopRRC, r2, c); - - // set carry from bit 31 of rotated constant if constant rotation was - // non-zero - if(shifterSetsCOut(shiftCOut) && state->info.crotate) { - armEmitMoveRC(state, 8, ARM_CF, (c & 0x80000000) ? 1 : 0); - } -} - -// -// Binop with three registers -// -ARM_MORPH_FN(armEmitBinopR) { - EMIT_BINOP_NO_SHIFT(state, armEmitBinopRRR, r2, GET_RS(state, r3)); -} - -// -// Binop with two registers (Thumb variant) -// -ARM_MORPH_FN(armEmitBinopRT) { - EMIT_BINOP_NO_SHIFT(state, armEmitBinopRRR, r1, GET_RS(state, r2)); -} - -// -// Binop with register and immediate (Thumb variant) -// -ARM_MORPH_FN(armEmitBinopIT) { - EMIT_BINOP_NO_SHIFT(state, armEmitBinopRRC, r1, state->info.c); -} - -// -// Binop with register, program counter and immediate (ADR) -// -ARM_MORPH_FN(armEmitBinopADR) { - Uns32 c = state->attrs->negate ? -state->info.c : state->info.c; - EMIT_BINOP_NO_SHIFT(state, armEmitBinopRRC, r2, alignConstWithPC(state, c)); -} - -// -// Binop with register shifted by immediate addressing mode -// -ARM_MORPH_FN(armEmitBinopRSI) { - EMIT_BINOP_SHIFT( - state, r2, rs2, - getShiftedRC(state, rs2, GET_RS(state, r3), shiftCOut) - ); -} - -// -// Binop with rotate right with extend addressing mode -// -ARM_MORPH_FN(armEmitBinopRX) { - EMIT_BINOP_SHIFT( - state, r2, rs2, - getExtendedR(state, rs2, GET_RS(state, r3), shiftCOut) - ); -} - - -//////////////////////////////////////////////////////////////////////////////// -// CMPOPS -//////////////////////////////////////////////////////////////////////////////// - -// -// Macro for emission of declarations for generic cmpop -// -#define EMIT_CMPOP_DECLS(_S) \ - vmiReg rd = VMI_NOREG; \ - vmiReg rs1 = GET_RS(_S, r1); \ - vmiBinop op = _S->attrs->binop; \ - vmiFlagsCP opFlags = getFlagsOrCIn(_S, rd); \ - vmiFlagsCPU shiftCOut = getShifterCOut(_S, rd) - -// -// Macro for emission of call implementing generic cmpop -// -#define EMIT_CMPOP_CALL(_S, _F, _S2) \ - _F(_S, ARM_GPR_BITS, op, rd, rs1, _S2, opFlags) - -// -// Macro for emission of generic cmpop with unshifted argument -// -#define EMIT_CMPOP_NO_SHIFT(_S, _F, _S2) \ - EMIT_CMPOP_DECLS(_S); \ - EMIT_CMPOP_CALL(_S, _F, _S2) - -// -// Macro for emission of generic cmpop with shifted argument -// -#define EMIT_CMPOP_SHIFT(_S, _RS2, _T) \ - EMIT_CMPOP_DECLS(_S); \ - vmiReg _RS2 = newTemp32(_S); \ - _T; \ - EMIT_CMPOP_CALL(_S, armEmitBinopRRR, _RS2); \ - freeTemp32(_S) - -// -// Cmpop with immediate -// -ARM_MORPH_FN(armEmitCmpopI) { - - Uns32 c = state->info.c; - - // emit register/constant cmpop with unshifted argument - EMIT_CMPOP_NO_SHIFT(state, armEmitBinopRRC, c); - - // set carry from bit 31 of rotated constant if constant rotation was - // non-zero - if(shifterSetsCOut(shiftCOut) && state->info.crotate) { - armEmitMoveRC(state, 8, ARM_CF, (c & 0x80000000) ? 1 : 0); - } -} - -// -// Cmpop with register -// -ARM_MORPH_FN(armEmitCmpopR) { - EMIT_CMPOP_NO_SHIFT(state, armEmitBinopRRR, GET_RS(state, r2)); -} - -// -// Cmpop with register shifted by immediate addressing mode -// -ARM_MORPH_FN(armEmitCmpopRSI) { - EMIT_CMPOP_SHIFT( - state, rs2, - getShiftedRC(state, rs2, GET_RS(state, r2), shiftCOut) - ); -} - -// -// Cmpop with rotate right with extend addressing mode -// -ARM_MORPH_FN(armEmitCmpopRX) { - EMIT_CMPOP_SHIFT( - state, rs2, - getExtendedR(state, rs2, GET_RS(state, r2), shiftCOut) - ); -} - - -//////////////////////////////////////////////////////////////////////////////// -// MULTIPLY AND DIVIDE INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code for MUL instruction -// -ARM_MORPH_FN(armEmitMUL) { - - vmiFlagsCP flags = getFlagsOrNull(state); - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - vmiReg rs = GET_RS(state, r3); - - armEmitBinopRRR(state, ARM_GPR_BITS, vmi_IMUL, rd, rm, rs, flags); -} - -// -// Emit code for SDIV and UDIV instructions -// -ARM_MORPH_FN(armEmitDIV) { - - vmiBinop op = state->attrs->binop; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - - // record the target of the divide instruction (in case of exception) - armEmitMoveRC(state, 8, ARM_DIVIDE_TARGET, state->info.r1); - armEmitBinopRRR(state, ARM_GPR_BITS, op, rd, rn, rm, 0); -} - -// -// Emit code for MLA or MLS instructions -// -static void emitMLAMLS(armMorphStateP state, vmiBinop op) { - - vmiFlagsCP flags = getFlagsOrNull(state); - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - vmiReg rs = GET_RS(state, r3); - vmiReg rn = GET_RS(state, r4); - vmiReg t = VMI_REG_EQUAL(rd, rn) ? getTemp(state) : rd; - - armEmitBinopRRR(state, ARM_GPR_BITS, vmi_IMUL, t, rm, rs, 0); - armEmitBinopRRR(state, ARM_GPR_BITS, op, rd, t, rn, flags); -} - -// -// MLA instruction -// -ARM_MORPH_FN(armEmitMLA) { - emitMLAMLS(state, vmi_ADD); -} - -// -// MLS instruction -// -ARM_MORPH_FN(armEmitMLS) { - emitMLAMLS(state, vmi_RSUB); -} - -// -// [SU]MULL instructions -// -ARM_MORPH_FN(armEmitMULL) { - - vmiBinop op = state->attrs->binop; - vmiFlagsCP flags = getFlagsOrNull(state); - vmiReg rdlo = GET_RD(state, r1); - vmiReg rdhi = GET_RD(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg rs = GET_RS(state, r4); - - armEmitMulopRRR(state, ARM_GPR_BITS, op, rdhi, rdlo, rm, rs, flags); -} - -// -// [SU]MLAL instructions -// -ARM_MORPH_FN(armEmitMLAL) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop op = state->attrs->binop; - vmiFlagsCP flags = getFlagsOrNull(state); - vmiReg rdlo = GET_RS(state, r1); - vmiReg rdhi = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg rs = GET_RS(state, r4); - vmiReg t = newTemp64(state); - vmiReg t164lo = getR64Lo(t); - vmiReg t164hi = getR64Hi(t); - - // perform initial multiply, result in temporary t164lo/t164hi - armEmitMulopRRR(state, bits, op, t164hi, t164lo, rm, rs, 0); - - if(VMI_REG_EQUAL(rdhi, getR64Hi(rdlo))) { - - // rdlo/rdhi are an adjacent pair - armEmitBinopRR(state, bits*2, vmi_ADD, rdlo, t164lo, flags); - - } else { - - // rdlo/rdhi are not an adjacent pair - vmiReg t = newTemp64(state); - vmiReg t264lo = getR64Lo(t); - vmiReg t264hi = getR64Hi(t); - - // move rdlo/rdhi into adjacent pair - armEmitMoveRR(state, bits, t264hi, rdhi); - armEmitMoveRR(state, bits, t264lo, rdlo); - - // perform addition using adjacent pair - armEmitBinopRR(state, bits*2, vmi_ADD, t264lo, t164lo, flags); - - // move to rdlo/rdhi from adjacent pair - armEmitMoveRR(state, bits, rdhi, t264hi); - armEmitMoveRR(state, bits, rdlo, t264lo); - - freeTemp64(state); - } - - freeTemp64(state); -} - - -//////////////////////////////////////////////////////////////////////////////// -// BRANCH INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Return link address from state -// -static Uns32 getStateLinkPC(armMorphStateP state) { - return state->nextPC | (IN_THUMB_MODE(state->arm) ? 1 : 0); -} - -// -// Fill armJumpInfo structure with information about a jump to a target address -// -static void seedJumpInfo( - armJumpInfoP ji, - armMorphStateP state, - Bool isLink, - Bool isReturn, - Bool isRelative -) { - ji->linkReg = isLink ? ARM_LR : VMI_NOREG; - ji->hint = isRelative ? vmi_JH_RELATIVE : vmi_JH_NONE; - ji->hint |= isReturn ? vmi_JH_RETURN : isLink ? vmi_JH_CALL : vmi_JH_NONE; - ji->linkPC = isLink ? getStateLinkPC(state) : 0; -} - -// -// Emit an explicit unconditional jump to target address -// -static void emitUncondJumpC(armMorphStateP state, Bool isLink) { - - // get information about the jump - armJumpInfo ji; - seedJumpInfo(&ji, state, isLink, False, True); - - // do the jump - armEmitUncondJump(state, &ji); -} - -// -// Emit an explicit conditional jump to target address -// -static void emitCondJumpC( - armMorphStateP state, - vmiReg tf, - Bool jumpIfTrue, - Bool isLink -) { - // get information about the jump - armJumpInfo ji; - seedJumpInfo(&ji, state, isLink, False, True); - - // do the jump - armEmitCondJump(state, &ji, tf, jumpIfTrue); -} - -// -// Macro defining the body of a (possibly conditional) jump to target -// -#define COND_OR_UNCOND_BRANCH_BODY(_UNCOND_CB, _COND_CB) \ - \ - armCond cond = emitPrepareCondition(state); \ - Bool isLink = state->attrs->isLink; \ - \ - if(cond.op==ACO_ALWAYS) { \ - /* unconditional jump */ \ - _UNCOND_CB(state, isLink); \ - } else { \ - /* conditional jump */ \ - _COND_CB(state, cond.flag, cond.op==ACO_TRUE, isLink); \ - } \ - -// -// Emit conditional branch to constant address, possibly with link -// -ARM_MORPH_FN(armEmitBranchC) { - COND_OR_UNCOND_BRANCH_BODY(emitUncondJumpC, emitCondJumpC); -} - -// -// Emit unconditional branch to register address, possibly with link -// -ARM_MORPH_FN(armEmitBranchR) { - - vmiReg ra = GET_RS(state, r1); - Bool isLink = state->attrs->isLink; - - // switch mode if LSB of target address implies a different mode - armEmitInterworkLSB(state, ra); - - // get information about the jump - armJumpInfo ji; - seedJumpInfo(&ji, state, isLink, state->info.r1==ARM_REG_LR, False); - - // do the jump - armEmitUncondJumpReg(state, &ji, ra); -} - - -//////////////////////////////////////////////////////////////////////////////// -// MISCELLANEOUS INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Called for an unimplemented instruction -// -static void ignoreBKPT(armP arm, Uns32 thisPC) { - - vmiMessage("W", CPU_PREFIX"_BII", - SRCREF_FMT "BKPT instruction ignored in nopBKPT compatability mode", - SRCREF_ARGS(arm, thisPC) - ); -} - -// -// Emit call to perform CLZ -// -ARM_MORPH_FN(armEmitCLZ) { - - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - - armEmitUnopRR(state, ARM_GPR_BITS, vmi_CLZ, rd, rm, 0); -} - -// -// Emit call to perform BKPT -// -ARM_MORPH_FN(armEmitBKPT) { - if(state->arm->compatMode==COMPAT_CODE_SOURCERY) { - armEmitArgProcessor(state); - armEmitArgSimPC(state, ARM_GPR_BITS); - armEmitCall(state, (vmiCallFn)ignoreBKPT); - } else { - emitExceptionCall(state, armBKPT); - } -} - -// -// Emit call to perform SWI -// -ARM_MORPH_FN(armEmitSWI) { - emitExceptionCall(state, armSWI); -} - - -//////////////////////////////////////////////////////////////////////////////// -// SPECIAL PURPOSE REGISTER ACCESS INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code for MRS -// -ARM_MORPH_FN(armEmitMRS) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rs = VMI_NOREG; - Bool privMode = !IN_USER_MODE(state->arm); - armSysRegId SYSm = state->info.c; - - switch(SYSm>>3) { - - case 0: { - - // extract fields from PSR - Uns32 mask = 0; - - // include exceptNum field if required - if((SYSm&1) && privMode) { - mask |= PSR_EXCEPT_NUM; - } - - // include flags field if required - if(!(SYSm&4)) { - mask |= PSR_FLAGS; - } - - // get masked result value - if(mask) { - armEmitArgProcessor(state); - armEmitCallResult(state, (vmiCallFn)armReadCPSR, bits, rd); - armEmitBinopRC(state, bits, vmi_AND, rd, mask, 0); - rs = rd; - } - - break; - } - - case 1: - - // return SP_main or SP_process - if(privMode) { - - // this code is mode specific - armEmitValidateBlockMask(ARM_BM_USE_SP_PROCESS); - - // select source register - if((SYSm&1) == USE_SP_PROCESS(state->arm)) { - rs = ARM_SP; - } else { - rs = ARM_BANK_SP; - } - } - - break; - - case 2: - - // return PRIMASK, BASEPRI, FAULTMASK or CONTROL - switch(SYSm&7) { - case 0: rs = privMode ? ARM_PRIMASK : VMI_NOREG; break; - case 1: rs = privMode ? ARM_BASEPRI : VMI_NOREG; break; - case 2: rs = privMode ? ARM_BASEPRI : VMI_NOREG; break; - case 3: rs = privMode ? ARM_FAULTMASK : VMI_NOREG; break; - case 4: rs = ARM_CONTROL; break; - default: break; - } - - break; - - default: - break; - } - - // get the register - armEmitMoveRR(state, bits, rd, rs); -} - -// -// Emit code for MSR -// -ARM_MORPH_FN(armEmitMSR) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rs = GET_RD(state, r1); - Bool privMode = !IN_USER_MODE(state->arm); - armSysRegId SYSm = state->info.c; - - switch(SYSm>>3) { - - case 0: { - - // insert fields in PSR - Uns32 wrMask = 0; - - // include flags field if required - if(!(SYSm&4)) { - armPSRBits bits = state->info.psrbits; - if (bits==ARM_PSRBITS_ALL || bits==ARM_PSRBITS_FLAGS) { - wrMask |= PSR_FLAGS; - } - if (bits==ARM_PSRBITS_ALL || bits==ARM_PSRBITS_GE) { - if (DSP_PRESENT(state->arm)) { - wrMask |= PSR_GE; - } - } - } - - // set masked result value - if(wrMask) { - armEmitArgProcessor(state); - armEmitArgReg(state, bits, rs); - armEmitArgUns32(state, wrMask); - armEmitCall(state, (vmiCallFn)armWriteCPSR); - } - - break; - } - - case 1: - - // set SP_main or SP_process - if(privMode) { - - vmiReg rd; - - // this code is mode specific - armEmitValidateBlockMask(ARM_BM_USE_SP_PROCESS); - - // select destination register - if((SYSm&1) == USE_SP_PROCESS(state->arm)) { - rd = ARM_SP; - } else { - rd = ARM_BANK_SP; - } - - // set the register - armEmitMoveRR(state, bits, rd, rs); - } - - break; - - case 2: - - // assign PRIMASK, BASEPRI, FAULTMASK or CONTROL - if(privMode) { - - switch(SYSm&7) { - - case 0: - armEmitArgProcessor(state); - armEmitArgReg(state, bits, rs); - armEmitCall(state, (vmiCallFn)armWritePRIMASK); - break; - - case 1: - armEmitArgProcessor(state); - armEmitArgReg(state, bits, rs); - armEmitCall(state, (vmiCallFn)armWriteBASEPRI); - break; - - case 2: - armEmitArgProcessor(state); - armEmitArgReg(state, bits, rs); - armEmitCall(state, (vmiCallFn)armWriteBASEPRI_MAX); - break; - - case 3: - armEmitArgProcessor(state); - armEmitArgReg(state, bits, rs); - armEmitCall(state, (vmiCallFn)armWriteFAULTMASK); - break; - - case 4: - armEmitArgProcessor(state); - armEmitArgReg(state, bits, rs); - armEmitCall(state, (vmiCallFn)armWriteCONTROL); - break; - - default: - break; - } - } - - break; - - default: - break; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// HINT INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit NOP -// -ARM_MORPH_FN(armEmitNOP) { - // no action -} - -// -// Emit WFE -// -ARM_MORPH_FN(armEmitWFE) { - - vmiLabelP wait = armEmitNewLabel(); - vmiLabelP done = armEmitNewLabel(); - - // jump to wait code if no event registered - armEmitCondJumpLabel(ARM_EVENT, False, wait); - - // clear event register and finish - armEmitMoveRC(state, 8, ARM_EVENT, 0); - armEmitUncondJumpLabel(done); - - // here if halt is required - armEmitInsertLabel(wait); - - // wait for event - armEmitWait(state, AD_WFE); - - // here when done - armEmitInsertLabel(done); -} - -// -// Emit WFI -// -ARM_MORPH_FN(armEmitWFI) { - - vmiLabelP noWait = armEmitNewLabel(); - - // don't stop if there are pending interrupts - armEmitCompareRCJumpLabel(8, vmi_COND_NZ, ARM_PENDING, 0, noWait); - - // halt the processor at the end of this instruction - armEmitWait(state, AD_WFI); - - // here if interrupt is currently pending - emitLabel(noWait); -} - -// -// Emit SEV -// -ARM_MORPH_FN(armEmitSEV) { - armEmitArgProcessor(state); - armEmitCall(state, (vmiCallFn)armSEV); -} - - -//////////////////////////////////////////////////////////////////////////////// -// LOAD AND STORE INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// This indicates that the register being loaded is also the base in an LDM -// -#define LDM_BASE_REG -1 - -// -// If this is an STM with the base register in the list and also writeback, is -// the value written the *final* value of the base register? -// -#define STM_WB_BASE_FINAL False - -// -// Callback function for load/store -// -#define LOAD_STORE_FN(_NAME) void _NAME( \ - armMorphStateP state, \ - vmiReg base, \ - Int32 offset \ -) -typedef LOAD_STORE_FN((*loadStoreFn)); - -// -// Callback function for one register of a load/store multiple -// -#define LOAD_STORE_M_FN(_NAME) void _NAME( \ - armMorphStateP state, \ - vmiReg base, \ - Int32 offset, \ - Uns32 r, \ - Bool isWBNotFirst, \ - Int32 frameDelta \ -) -typedef LOAD_STORE_M_FN((*loadStoreMFn)); - -// -// Should increment/decrement be performed before access? -// -inline static Bool doBefore(armMorphStateP state) { - armIncDec incDec = state->info.incDec; - return ((incDec==ARM_ID_IB) || (incDec==ARM_ID_DA)); -} - -// -// Does load/store multiple increment? -// -inline static Bool doIncrement(armMorphStateP state) { - return state->info.incDec & ARM_ID_I; -} - -// -// Return the step to apply before load/store multiple -// -inline static Int32 getStepBefore(armMorphStateP state, Uns32 bytes) { - return doBefore(state) ? bytes : 0; -} - -// -// Return the step to apply after load/store multiple -// -inline static Int32 getStepAfter(armMorphStateP state, Uns32 bytes) { - return doBefore(state) ? 0 : bytes; -} - -// -// Return frame size for a load/store multiple -// -static Uns32 getFrameSize(armMorphStateP state) { - - Uns32 rList = state->info.rList; - Uns32 mask; - Uns32 r; - Int32 size = 0; - - for(r=0, mask=1; rinfo.r1); - - return (isLoad && (state->info.rList & rmMask)); -} - -// -// Is the base register not the highest (first) register in the list? -// -inline static Bool baseIsNotFirst(Uns32 rList, Uns32 rBase) { - return rList & ((1<info.rList; - Uns32 rBase = state->info.r1; - Bool baseLoaded = baseIsLoaded(state, isLoad); - vmiReg base = GET_RS(state, r1); - Bool increment = doIncrement(state); - Int32 stepBefore = getStepBefore(state, ARM_GPR_BYTES); - Int32 stepAfter = getStepAfter(state, ARM_GPR_BYTES); - Uns32 frameSize = getFrameSize(state); - Int32 offset = increment ? 0 : -frameSize; - Int32 frameDelta = increment ? frameSize : -frameSize; - Bool isNotFirst = state->info.wb && baseIsNotFirst(rList, rBase); - Uns32 mask; - Uns32 r; - - // load or store registers - for(r=0, mask=1; rinfo.wb) { - vmiReg rn = GET_RD(state, r1); - armEmitBinopRRC(state, bits, vmi_ADD, rn, base, frameDelta, 0); - } -} - -// -// Macro to emit one register load for LDM -// -#define EMIT_LDM_REG(_S, _BASE, _OFFSET, _R) { \ - \ - Uns32 bits = ARM_GPR_BITS; \ - vmiReg rd = (_R==LDM_BASE_REG) ? getTemp(_S) : getRD(_S, _R); \ - \ - armEmitLoadRRO(_S, bits, _OFFSET, rd, _BASE, False, True); \ -} - -// -// Emit one register load for LDM -// -static LOAD_STORE_M_FN(emitLDMCB) { - EMIT_LDM_REG(state, base, offset, r); -} - -// -// If the source register is the PC, adjust to a 12-byte offset if required -// -static vmiReg emitPCDelta(armMorphStateP state, Uns32 r, vmiReg rs) { - - if((r==ARM_REG_PC) && state->arm->configInfo.STRoffsetPC12) { - vmiReg t = getTemp(state); - armEmitBinopRRC(state, ARM_GPR_BITS, vmi_ADD, t, rs, 4, 0); - return t; - } else { - return rs; - } -} - -// -// Emit one register store for STM -// -static LOAD_STORE_M_FN(emitSTMCB) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rs = getRS(state, r); - - // write the final value of the base register if it is in the register list - if(STM_WB_BASE_FINAL && isWBNotFirst) { - rs = getTemp(state); - armEmitBinopRRC(state, bits, vmi_ADD, rs, base, frameDelta, 0); - } - - // if source register is PC, allow for store offset adjustment - rs = emitPCDelta(state, r, rs); - - // do the store - armEmitStoreRRO(state, bits, offset, base, rs); -} - -// -// Emit code for LDM (1) -// -ARM_MORPH_FN(armEmitLDM1) { - emitLoadStoreMultiple(state, emitLDMCB, True); -} - -// -// Emit code for STM (1) -// -ARM_MORPH_FN(armEmitSTM1) { - emitLoadStoreMultiple(state, emitSTMCB, False); -} - -// -// Should the LDR instruction do writeback? -// -inline static Bool doLDRWriteBack(armMorphStateP state) { - return (state->info.wb && (state->info.r1!=state->info.r2)); -} - -// -// Is translation required? (LDRT, STRT) -// -inline static Bool doTranslate(armMorphStateP state) { - return (state->info.tl && IN_PRIV_MPU_MODE(state->arm)); -} - -// -// If this is an LDRT/STRT instruction and we are currently in privileged mode -// with TLB enabled, emit code to switch to the user mode data memDomain -// -static void emitTranslateOn(armMorphStateP state) { - if(doTranslate(state)) { - armEmitArgProcessor(state); - armEmitCall(state, (vmiCallFn)armVMSetUserPrivilegedModeDataDomain); - } -} - -// -// If this is after a LDRT/STRT instruction and we are currently in privileged -// mode with TLB enabled, emit code to switch back to the privileged mode data -// memDomain. Note that this code is not executed if the prior access causes an -// exception; in this case, mode is restored in armDataAbort. -// -static void emitTranslateOff(armMorphStateP state) { - if(doTranslate(state)) { - armEmitArgProcessor(state); - armEmitCall(state, (vmiCallFn)armVMRestoreNormalDataDomain); - } -} - -// -// Emit code for LDR variant -// -static LOAD_STORE_FN(emitLDR) { - - Uns32 memBits = state->info.sz*8; - Bool isLong = (memBits==64); - vmiReg rd = GET_RD(state, r1); - Bool xs = state->info.xs; - - // start translation (LDRT, STRT) - emitTranslateOn(state); - - // emit load - if(isLong) { - - vmiReg rdH = GET_RD(state, r4); - vmiReg rt = getTemp(state); - - armEmitLoadRRRO(state, memBits, offset, rd, rdH, base, rt, xs, False); - - } else { - - armEmitLoadRRO(state, memBits, offset, rd, base, xs, False); - } - - // end translation (LDRT, STRT) - emitTranslateOff(state); -} - -// -// Emit code for STR variant -// -static LOAD_STORE_FN(emitSTR) { - - Uns32 memBits = state->info.sz*8; - Bool isLong = (memBits==64); - Uns32 r1 = state->info.r1; - vmiReg rs = getRS(state, r1); - - // if source register is PC, allow for store offset adjustment - rs = emitPCDelta(state, r1, rs); - - // start translation (LDRT, STRT) - emitTranslateOn(state); - - // emit store - if(isLong) { - - Uns32 r4 = state->info.r4; - vmiReg rsH = getRS(state, r4); - - armEmitStoreRRRO(state, memBits, offset, base, rs, rsH); - - } else { - - armEmitStoreRRO(state, memBits, offset, base, rs); - } - - // end translation (LDRT, STRT) - emitTranslateOff(state); -} - -// -// Emit code for LDR/STR with immediate offset -// -static void emitLDRSTRI(armMorphStateP state, loadStoreFn cb, Bool align) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg base = GET_RS(state, r2); - Int32 offset = state->info.c; - Int32 memOffset = state->info.pi ? 0 : offset; - - // align the constant if the base register is the program counter (has - // effect for PC-relative Thumb load instructions only) - if(align && VMI_REG_EQUAL(base, ARM_PC)) { - memOffset = alignConstWithPC(state, memOffset); - } - - // emit register load or store - cb(state, base, memOffset); - - // do writeback if required - if(doLDRWriteBack(state)) { - vmiReg ra = GET_RD(state, r2); - armEmitBinopRC(state, bits, vmi_ADD, ra, offset, 0); - } -} - -// -// Emit code for LDR/STR variant -// -static void emitLDRSTRInt(armMorphStateP state, vmiReg offset, loadStoreFn cb) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg base = GET_RS(state, r2); - vmiReg t = newTemp32(state); - vmiReg memReg = state->info.pi ? base : t; - vmiBinop op = state->info.u ? vmi_ADD : vmi_SUB; - - // calculate incremented address - armEmitBinopRRR(state, bits, op, t, base, offset, 0); - - // emit register load - cb(state, memReg, 0); - - // do writeback if required - if(doLDRWriteBack(state)) { - vmiReg ra = GET_RD(state, r2); - armEmitMoveRR(state, bits, ra, t); - } - - freeTemp32(state); -} - -// -// Emit code for LDR/STR with register offset -// -static void emitLDRSTRR(armMorphStateP state, loadStoreFn cb) { - - vmiReg rm = GET_RS(state, r3); - - emitLDRSTRInt(state, rm, cb); -} - -// -// Emit code for LDR/STR with scaled register offset (LSL, LSR, ASR, ROR) -// -static void emitLDRSTRRSI(armMorphStateP state, loadStoreFn cb) { - - vmiReg t = newTemp32(state); - vmiReg rm = GET_RS(state, r3); - - getShiftedRC(state, t, rm, FLAGS_CIN); - - emitLDRSTRInt(state, t, cb); - - freeTemp32(state); -} - -// -// Emit code for LDR with immediate offset -// -ARM_MORPH_FN(armEmitLDRI) { - emitLDRSTRI(state, emitLDR, True); -} - -// -// Emit code for LDR with register offset -// -ARM_MORPH_FN(armEmitLDRR) { - emitLDRSTRR(state, emitLDR); -} - -// -// Emit code for LDR with scaled register offset (LSL, LSR, ASR, ROR) -// -ARM_MORPH_FN(armEmitLDRRSI) { - emitLDRSTRRSI(state, emitLDR); -} - -// -// Emit code for STR with immediate offset -// -ARM_MORPH_FN(armEmitSTRI) { - emitLDRSTRI(state, emitSTR, False); -} - -// -// Emit code for STR with register offset -// -ARM_MORPH_FN(armEmitSTRR) { - emitLDRSTRR(state, emitSTR); -} - -// -// Emit code for STR with scaled register offset (LSL, LSR, ASR, ROR) -// -ARM_MORPH_FN(armEmitSTRRSI) { - emitLDRSTRRSI(state, emitSTR); -} - - -//////////////////////////////////////////////////////////////////////////////// -// DSP INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Minimum and maximum values for clamping -// -#define ARM_MIN 0x80000000 -#define ARM_MAX 0x7fffffff - -// -// Emit code for to perform rd = rs1 op rs2, clamping result and setting Q -// flag if overflow -// -static void emitOpSetQClamp( - armMorphStateP state, - vmiBinop op, - vmiReg rd, - vmiReg rs1, - vmiReg rs2 -) { - Uns32 bits = ARM_GPR_BITS; - vmiFlags flags = getSFOFFlags(getTemp(state)); - vmiLabelP noOverflow = armEmitNewLabel(); - - // do the operation, setting flags - armEmitBinopRRR(state, bits, op, rd, rs1, rs2, &flags); - - // skip clamping and Q flag update unless there was an overflow - armEmitCondJumpLabel(flags.f[vmi_OF], False, noOverflow); - - // clamp depending on sign of result - armEmitCondMoveRCC(state, bits, flags.f[vmi_SF], True, rd, ARM_MAX, ARM_MIN); - - // set the sticky Q flag - armEmitMoveRC(state, 8, ARM_QF, 1); - - // here if the operation didn't overflow - emitLabel(noOverflow); -} - -// -// Emit code to perform rd = rs1 op rs2, setting Q flag if overflow -// -static void emitOpSetQ( - armMorphStateP state, - Uns32 bits, - vmiBinop op, - vmiReg rd, - vmiReg rs1, - vmiReg rs2 -) { - vmiReg tf = getTemp(state); - vmiFlags flags = getOFFlags(tf); - - // do the operation, setting flags - armEmitBinopRRR(state, bits, op, rd, rs1, rs2, &flags); - - // set the sticky Q flag of there was overflow - armEmitBinopRR(state, 8, vmi_OR, ARM_QF, tf, 0); -} - -// -// Emit code for 16 x 16 = 32 multiply -// -static void emitMul1632( - armMorphStateP state, - vmiReg rd, - vmiReg rs1, - vmiReg rs2 -) { - vmiReg rdlo = getR32Lo(rd); - vmiReg rdhi = getR32Hi(rd); - - // do 16 x 16 = 32 multiply - armEmitMulopRRR(state, ARM_GPR_BITS/2, vmi_IMUL, rdhi, rdlo, rs1, rs2, 0); -} - -// -// Emit code for QADD/QSUB -// -static void emitQADDSUB(armMorphStateP state, vmiBinop op) { - - vmiReg rd = GET_RD(state, r1); - vmiReg rs1 = GET_RS(state, r2); - vmiReg rs2 = GET_RS(state, r3); - - emitOpSetQClamp(state, op, rd, rs1, rs2); -} - -// -// Emit code for QDADD/QDSUB -// -static void emitQDADDSUB(armMorphStateP state, vmiBinop op) { - - vmiReg rd = GET_RD(state, r1); - vmiReg rs1 = GET_RS(state, r2); - vmiReg rs2 = GET_RS(state, r3); - vmiReg t = newTemp32(state); - - emitOpSetQClamp(state, vmi_ADD, t, rs2, rs2); - emitOpSetQClamp(state, op, rd, rs1, t); - - freeTemp32(state); -} - -// -// Emit code for QADD -// -ARM_MORPH_FN(armEmitQADD) { - emitQADDSUB(state, vmi_ADD); -} - -// -// Emit code for QSUB -// -ARM_MORPH_FN(armEmitQSUB) { - emitQADDSUB(state, vmi_SUB); -} - -// -// Emit code for QDADD -// -ARM_MORPH_FN(armEmitQDADD) { - emitQDADDSUB(state, vmi_ADD); -} - -// -// Emit code for QDSUB -// -ARM_MORPH_FN(armEmitQDSUB) { - emitQDADDSUB(state, vmi_SUB); -} - -// -// Emit code for SMLA -// -static void emitSMLA(armMorphStateP state, Uns32 xDelta, Uns32 yDelta) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rs1 = VMI_REG_DELTA(GET_RS(state, r2), xDelta); - vmiReg rs2 = VMI_REG_DELTA(GET_RS(state, r3), yDelta); - vmiReg rs3 = GET_RS(state, r4); - vmiReg t = newTemp32(state); - - // do 16 x 16 = 32 multiply - emitMul1632(state, t, rs1, rs2); - - // do the accumulate, setting Q flag on overflow - emitOpSetQ(state, bits, vmi_ADD, rd, rs3, t); - - // free multiply result temporary - freeTemp32(state); -} - -// -// Emit code for SMLABB -// -ARM_MORPH_FN(armEmitSMLABB) { - emitSMLA(state, 0, 0); -} - -// -// Emit code for SMLABT -// -ARM_MORPH_FN(armEmitSMLABT) { - emitSMLA(state, 0, 2); -} - -// -// Emit code for SMLATB -// -ARM_MORPH_FN(armEmitSMLATB) { - emitSMLA(state, 2, 0); -} - -// -// Emit code for SMLATT -// -ARM_MORPH_FN(armEmitSMLATT) { - emitSMLA(state, 2, 2); -} - -// -// Emit code for SMLAL -// -static void emitSMLAL(armMorphStateP state, Uns32 xDelta, Uns32 yDelta) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rdlo = GET_RD(state, r1); - vmiReg rdhi = GET_RD(state, r2); - vmiReg rs1 = VMI_REG_DELTA(GET_RS(state, r3), xDelta); - vmiReg rs2 = VMI_REG_DELTA(GET_RS(state, r4), yDelta); - vmiReg t = newTemp64(state); - vmiReg tlo32 = getR64Lo(t); - vmiReg thi32 = getR64Hi(t); - vmiFlags flags = getCFFlags(getTemp(state)); - - // do 16 x 16 = 32 multiply and extend to 64 bits - emitMul1632(state, t, rs1, rs2); - armEmitMoveExtendRR(state, bits*2, t, bits, tlo32, True); - - // do the accumulate - armEmitBinopRR(state, bits, vmi_ADD, rdlo, tlo32, &flags); - armEmitBinopRR(state, bits, vmi_ADC, rdhi, thi32, &flags); - - // free multiply result temporary - freeTemp64(state); -} - -// -// Emit code for SMLABB -// -ARM_MORPH_FN(armEmitSMLALBB) { - emitSMLAL(state, 0, 0); -} - -// -// Emit code for SMLABT -// -ARM_MORPH_FN(armEmitSMLALBT) { - emitSMLAL(state, 0, 2); -} - -// -// Emit code for SMLATB -// -ARM_MORPH_FN(armEmitSMLALTB) { - emitSMLAL(state, 2, 0); -} - -// -// Emit code for SMLATT -// -ARM_MORPH_FN(armEmitSMLALTT) { - emitSMLAL(state, 2, 2); -} - -// -// Emit code for SMLAW -// -static void emitSMLAW(armMorphStateP state, Uns32 yDelta) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rs1 = GET_RS(state, r2); - vmiReg rs2 = VMI_REG_DELTA(GET_RS(state, r3), yDelta); - vmiReg rs3 = GET_RS(state, r4); - vmiReg t = newTemp64(state); - vmiReg tlo32 = getR64Lo(t); - vmiReg thi32 = getR64Hi(t); - vmiReg t48 = VMI_REG_DELTA(t, 2); - - // sign extend rs2 and place result in temporary - armEmitMoveExtendRR(state, bits, t, bits/2, rs2, True); - - // do 32 x 32 = 64 multiply - armEmitMulopRRR(state, bits, vmi_IMUL, thi32, tlo32, t, rs1, 0); - - // do the accumulate, setting Q flag on overflow - emitOpSetQ(state, bits, vmi_ADD, rd, t48, rs3); - - // free multiply result temporary - freeTemp64(state); -} - -// -// Emit code for SMLAWB -// -ARM_MORPH_FN(armEmitSMLAWB) { - emitSMLAW(state, 0); -} - -// -// Emit code for SMLAWT -// -ARM_MORPH_FN(armEmitSMLAWT) { - emitSMLAW(state, 2); -} - -// -// Emit code for emitSMUL -// -static void emitSMUL(armMorphStateP state, Uns32 xDelta, Uns32 yDelta) { - - vmiReg rd = GET_RD(state, r1); - vmiReg rs1 = VMI_REG_DELTA(GET_RS(state, r2), xDelta); - vmiReg rs2 = VMI_REG_DELTA(GET_RS(state, r3), yDelta); - - emitMul1632(state, rd, rs1, rs2); -} - -// -// Emit code for SMULBB -// -ARM_MORPH_FN(armEmitSMULBB) { - emitSMUL(state, 0, 0); -} - -// -// Emit code for SMULBT -// -ARM_MORPH_FN(armEmitSMULBT) { - emitSMUL(state, 0, 2); -} - -// -// Emit code for SMULTB -// -ARM_MORPH_FN(armEmitSMULTB) { - emitSMUL(state, 2, 0); -} - -// -// Emit code for SMULTT -// -ARM_MORPH_FN(armEmitSMULTT) { - emitSMUL(state, 2, 2); -} - -// -// Emit code for SMULW -// -static void emitSMULW(armMorphStateP state, Uns32 yDelta) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rs1 = GET_RS(state, r2); - vmiReg rs2 = VMI_REG_DELTA(GET_RS(state, r3), yDelta); - vmiReg t = newTemp64(state); - vmiReg tlo32 = getR64Lo(t); - vmiReg thi32 = getR64Hi(t); - vmiReg t48 = VMI_REG_DELTA(t, 2); - - // sign extend rs2 and place result in temporary - armEmitMoveExtendRR(state, bits, t, bits/2, rs2, True); - - // do 32 x 32 = 64 multiply - armEmitMulopRRR(state, bits, vmi_IMUL, thi32, tlo32, t, rs1, 0); - - // assign the result - armEmitMoveRR(state, bits, rd, t48); - - // free multiply result temporary - freeTemp64(state); -} - -// -// Emit code for SMULWB -// -ARM_MORPH_FN(armEmitSMULWB) { - emitSMULW(state, 0); -} - -// -// Emit code for SMULWT -// -ARM_MORPH_FN(armEmitSMULWT) { - emitSMULW(state, 2); -} - -//////////////////////////////////////////////////////////////////////////////// -// COPROCESSOR INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Morpher callback for undefined coprocessor instructions -// -ARM_MORPH_FN(armEmitUsageFaultCP) { - - // generate assertion - armEmitArgProcessor(state); - armEmitArgSimPC(state, ARM_GPR_BITS); - armEmitCall(state, (vmiCallFn)undefinedCPMessage); - - // take UndefinedInstruction exception - emitUsageFault(state, EXC_UNDEF_NOCP); -} - - - -//////////////////////////////////////////////////////////////////////////////// -// MOVE INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// MOVW instruction -// -ARM_MORPH_FN(armEmitMOVW) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - - armEmitMoveRC(state, bits, rd, state->info.c); -} - -// -// MOVT instruction -// -ARM_MORPH_FN(armEmitMOVT) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - - if(!VMI_REG_EQUAL(rd, ARM_PC)) { - - vmiReg rdH = VMI_REG_DELTA(rd, 2); - - armEmitMoveRC(state, bits/2, rdH, state->info.c); - - } else { - - vmiReg rs = getRS(state, ARM_REG_PC); - vmiReg tmp = newTemp32(state); - vmiReg tmpH = VMI_REG_DELTA(tmp, 2); - - armEmitMoveRR(state, bits, tmp, rs); - armEmitMoveRC(state, bits/2, tmpH, state->info.c); - armEmitMoveRR(state, bits, rd, tmp); - - freeTemp32(state); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// MULTIPLY INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// [SU]MAAL instructions -// -ARM_MORPH_FN(armEmitMAAL) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop op = state->attrs->binop; - vmiReg rdlo = GET_RS(state, r1); - vmiReg rdhi = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg rs = GET_RS(state, r4); - vmiReg t = newTemp64(state); - vmiReg t64lo = getR64Lo(t); - vmiReg t64hi = getR64Hi(t); - vmiFlags tf = getCFFlags(getTemp(state)); - - // perform initial multiply, result in temporary t64lo/t64hi - armEmitMulopRRR(state, bits, op, t64hi, t64lo, rm, rs, 0); - - // add in rdhi - armEmitBinopRR(state, bits, vmi_ADD, t64lo, rdhi, &tf); - armEmitBinopRC(state, bits, vmi_ADC, t64hi, 0, &tf); - - // add in rdlo - armEmitBinopRR(state, bits, vmi_ADD, t64lo, rdlo, &tf); - armEmitBinopRC(state, bits, vmi_ADC, t64hi, 0, &tf); - - // move result to rdlo/rdhi - armEmitMoveRR(state, bits, rdhi, t64hi); - armEmitMoveRR(state, bits, rdlo, t64lo); - - freeTemp64(state); -} - -//////////////////////////////////////////////////////////////////////////////// -// SYNCHRONIZATION INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Generate exclusive access tag address ra+offset in register rtag -// -static void generateEATag( - armMorphStateP state, - Uns32 offset, - vmiReg rtag, - vmiReg ra -) { - Uns32 bits = ARM_GPR_BITS; - Uns32 mask = state->arm->exclusiveTagMask; - - armEmitBinopRRC(state, bits, vmi_ADD, rtag, ra, offset, 0); - armEmitBinopRC(state, bits, vmi_AND, rtag, mask, 0); -} - -// -// Emit code to start exclusive access to address ra+offset -// -inline static void startEA(armMorphStateP state, Uns32 offset, vmiReg ra) { - generateEATag(state, offset, ARM_EA_TAG, ra); -} - -// -// Validate the exclusive access and jump to label 'done' if it is invalid, -// setting rd to 1 -// -static vmiLabelP validateEA( - armMorphStateP state, - Uns32 offset, - vmiReg ra, - vmiReg rd -) { - Uns32 bits = ARM_GPR_BITS; - Uns32 memBits = state->info.sz*8; - vmiLabelP done = armEmitNewLabel(); - vmiLabelP ok = armEmitNewLabel(); - vmiReg t = getTemp(state); - - // generate any store exception prior to exclusive access tag check - armEmitTryStoreRC(state, memBits, offset, ra); - - // generate exclusive access tag for this address - generateEATag(state, offset, t, ra); - - // do load and store tags match? - armEmitCompareRR(state, bits, vmi_COND_EQ, ARM_EA_TAG, t, t); - - // commit store if tags match - armEmitCondJumpLabel(t, True, ok); - - // indicate store failed - armEmitMoveRC(state, bits, rd, 1); - - // jump to instruction end - armEmitUncondJumpLabel(done); - - // here to commit store - armEmitInsertLabel(ok); - - return done; -} - -// -// Do actions required to terminate exclusive access -// -static void clearEA(armMorphStateP state) { - - // exclusiveTag becomes ARM_NO_TAG to indicate no active access - armEmitMoveRC(state, ARM_GPR_BITS, ARM_EA_TAG, ARM_NO_TAG); -} - -// -// Do actions required to complete exclusive access -// -static void endEA(armMorphStateP state, vmiReg rd, vmiLabelP done) { - - // indicate store succeeded - armEmitMoveRC(state, ARM_GPR_BITS, rd, 0); - - // insert target label for aborted stores - armEmitInsertLabel(done); - - // terminate exclusive access - clearEA(state); -} - -// -// Emit code for LDREX* -// -ARM_MORPH_FN(armEmitLDREX) { - - // indicate LDREX is now active at address r2+offset - startEA(state, state->info.c, GET_RS(state, r2)); - - // emit load - armEmitLDRI(state); -} - -// -// Emit code for STREX* -// -ARM_MORPH_FN(armEmitSTREX) { - - // validate STREX attempt at address r3+offset - vmiReg rd = GET_RD(state, r1); - vmiLabelP done = validateEA(state, state->info.c, GET_RS(state, r3), rd); - - // move down rt and rn so that they are in the required positions for a - // normal store - state->info.r1 = state->info.r2; - state->info.r2 = state->info.r3; - - // emit store - armEmitSTRI(state); - - // complete STREX attempt - endEA(state, rd, done); -} - -// -// Emit code for CLREX -// -ARM_MORPH_FN(armEmitCLREX) { - clearEA(state); -} - - -//////////////////////////////////////////////////////////////////////////////// -// MISCELLANEOUS INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Function to set PRIMASK and/or FAULTMASK -// -static void setMasks(armP arm, armFlagAffect faff) { - - Bool updateState = False; - - // set PRIMASK if required - if((faff&ARM_FAFF_I) && !arm->sregs.PRIMASK) { - arm->sregs.PRIMASK = 1; - updateState = True; - } - - // set FAULTMASK if required - if((faff&ARM_FAFF_F) && !arm->sregs.FAULTMASK && (arm->executionPriority>-1)) { - arm->sregs.FAULTMASK = 1; - updateState = True; - } - - // update processor state if required - if(updateState) { - armRefreshExecutionPriority(arm); - } -} - -// -// Function to clear PRIMASK and/or FAULTMASK -// -static void clearMasks(armP arm, armFlagAffect faff) { - - Bool updateState = False; - - // set PRIMASK if required - if((faff&ARM_FAFF_I) && arm->sregs.PRIMASK) { - arm->sregs.PRIMASK = 0; - updateState = True; - } - - // set FAULTMASK if required - if((faff&ARM_FAFF_F) && arm->sregs.FAULTMASK) { - arm->sregs.FAULTMASK = 0; - updateState = True; - } - - // update processor state if required - if(updateState) { - armRefreshExecutionPriority(arm); - } -} - -// -// Emit code for CPS -// -ARM_MORPH_FN(armEmitCPS) { - - if(!IN_USER_MODE(state->arm)) { - - armFlagAffect faff = state->info.faff; - Bool set = (state->info.fact==ARM_FACT_ID); - - // emit call to set or clear the masks - armEmitArgProcessor(state); - armEmitArgUns32(state, faff); - armEmitCall(state, set ? (vmiCallFn)setMasks : (vmiCallFn)clearMasks); - - // terminate the current code block - armEmitEndBlock(); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// BRANCH INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code for CPZ/CBNZ -// -ARM_MORPH_FN(armEmitCBZ) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rn = GET_RS(state, r1); - vmiReg tf = getTemp(state); - - // do the comparison - armEmitCompareRC(state, bits, vmi_COND_Z, rn, 0, tf); - - // get information about the jump - armJumpInfo ji; - seedJumpInfo(&ji, state, False, False, True); - - // do the jump - armEmitCondJump(state, &ji, tf, state->attrs->jumpIfTrue); -} - -// -// Emit code for TBB/TBH -// -ARM_MORPH_FN(armEmitTB) { - - Uns32 bits = ARM_GPR_BITS; - Uns32 sz = state->info.sz; - Uns32 memBits = sz*8; - vmiReg rn = GET_RS(state, r1); - vmiReg rm = GET_RS(state, r2); - vmiReg t1 = getTemp(state); - Uns32 shift = 0; - - // convert from size to shift - while(sz>1) { - sz >>= 1; - shift++; - } - - // get offset, shifted if required - armEmitBinopRRC(state, bits, vmi_SHL, t1, rm, shift, 0); - - // compose full address - armEmitBinopRR(state, bits, vmi_ADD, t1, rn, 0); - - // load zero-extended offset from table and double it - armEmitLoadRRO(state, memBits, 0, t1, t1, False, False); - armEmitBinopRR(state, bits, vmi_ADD, t1, t1, 0); - - // add to effective PC to get target address - armEmitBinopRR(state, bits, vmi_ADD, t1, getRS(state, ARM_REG_PC), 0); - - // get information about the jump - armJumpInfo ji; - seedJumpInfo(&ji, state, False, False, True); - - // do the jump - armEmitUncondJumpReg(state, &ji, t1); -} - - -//////////////////////////////////////////////////////////////////////////////// -// BASIC MEDIA INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Common routine for USAD8 and USADA8 -// -static void emitUSAD8Int(armMorphStateP state, vmiReg ra) { - - Uns32 bits = ARM_GPR_BITS; - Uns32 partBits = 8; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1 = newTemp32(state); - vmiReg t2 = newTemp32(state); - vmiReg t3 = getTemp(state); - Uns32 i; - - // clear result accumulators - armEmitMoveRR(state, bits, t1, ra); - - for(i=0; i<(bits/partBits); i++) { - - // get zero-extended arguments in temporaries - armEmitMoveExtendRR(state, bits, t2, partBits, rn, False); - armEmitMoveExtendRR(state, bits, t3, partBits, rm, False); - - // perform subtraction - armEmitBinopRR(state, bits, vmi_SUB, t2, t3, 0); - - // get absolute result - armEmitUnopRR(state, bits, vmi_ABS, t2, t2, 0); - - // update accumulated result - armEmitBinopRR(state, bits, vmi_ADD, t1, t2, 0); - - // step to next register pair - rn = VMI_REG_DELTA(rn, 1); - rm = VMI_REG_DELTA(rm, 1); - } - - // assign result register - armEmitMoveRR(state, bits, rd, t1); - - // free allocated temporaries - freeTemp32(state); - freeTemp32(state); -} - -// -// Common routine for SBFX and UBFX -// -static void emitBFXInt(armMorphStateP state, vmiBinop op) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - Uns32 lsb = state->info.c; - Uns32 msb = lsb + state->info.w - 1; - - if(msbinfo.c; - Int32 width = state->info.w; - - if(width<=0) { - - // no action - - } else if(width==bits) { - - // optimize to a move - armEmitMoveRC(state, bits, rd, 0); - - } else { - - // general case - Uns32 mask1 = ((1<info.c; - Int32 width = state->info.w; - - if(width<=0) { - - // no action - - } else if(width==bits) { - - // optimize to a move - armEmitMoveRR(state, bits, rd, rs); - - } else { - - // general case - vmiReg t = getTemp(state); - Uns32 mask1 = ((1<attrs->setGE) { - armEmitBinopRC(state, ARM_GPR_BITS, vmi_AND, ARM_PSR, ~PSR_GE30, 0); - } -} - -// -// Emit code to perform part of a parallel operation -// -static void emitParallelBinopInt( - armMorphStateP state, - Uns32 partBits, - vmiBinop op, - vmiReg rd, - vmiReg rn, - vmiReg rm, - Uns32 delta1, - Uns32 delta2, - Uns32 apsrMask -) { - Bool setGE = state->attrs->setGE; - Bool sextend = state->attrs->sextend; - Bool halve = state->attrs->halve; - vmiFlags flags = VMI_NOFLAGS; - vmiReg tf = newTemp32(state); - vmiReg rnTmp; - vmiReg rmTmp; - vmiReg rdTmp; - Uns32 opBits; - - // set up flags to generate CPSR greater-or-equal bits if required - if(!(setGE || halve)) { - // no action - } else if(sextend) { - flags.f[vmi_SF] = tf; - } else { - flags.f[vmi_CF] = flags.cin = tf; - } - - // get shift to appropriate part of each register - rd = VMI_REG_DELTA(rd, delta1); - rn = VMI_REG_DELTA(rn, delta1); - rm = VMI_REG_DELTA(rm, delta2); - - // argument format depends on whether sign extension is required - if(sextend) { - - // sign extension required: perform operation on extended arguments - opBits = ARM_GPR_BITS; - rdTmp = newTemp32(state); - rnTmp = rdTmp; - rmTmp = getTemp(state); - - // sign extend arguments into temporaries - armEmitMoveExtendRR(state, opBits, rnTmp, partBits, rn, True); - armEmitMoveExtendRR(state, opBits, rmTmp, partBits, rm, True); - - } else { - - // use original unextended arguments - opBits = partBits; - rdTmp = rd; - rnTmp = rn; - rmTmp = rm; - } - - // do the operation - armEmitBinopRRR(state, opBits, op, rdTmp, rnTmp, rmTmp, &flags); - - // update CPSR greater-or-equal bits if required - if(setGE) { - - vmiLabelP done = armEmitNewLabel(); - - // skip flag update if required - armEmitCondJumpLabel(tf, (sextend || (op!=vmi_ADD)), done); - - // include apsrMask in CPSR register - armEmitBinopRC(state, ARM_GPR_BITS, vmi_OR, ARM_PSR, apsrMask, 0); - - // jump to here if flag update is not required - armEmitInsertLabel(done); - } - - // halve results if required - if(!halve) { - // no action - } else if(sextend) { - armEmitBinopRC(state, opBits, vmi_SHR, rdTmp, 1, 0); - } else { - armEmitBinopRC(state, opBits, vmi_RCR, rdTmp, 1, &flags); - } - - // write back temporary if required - if(sextend) { - armEmitMoveRR(state, partBits, rd, rdTmp); - freeTemp32(state); - } - - // free temporary flag - freeTemp32(state); -} - -// -// Emit code for parallel add/subtract of 8-bit data -// -ARM_MORPH_FN(armEmitParallelBinop8) { - - Uns32 bits = ARM_GPR_BITS/4; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiBinop op = state->attrs->binop; - - // clear GE flags - emitClearGEFlags(state); - - // perform the parallel operations - emitParallelBinopInt(state, bits, op, rd, rn, rm, 0, 0, PSR_GE0); - emitParallelBinopInt(state, bits, op, rd, rn, rm, 1, 1, PSR_GE1); - emitParallelBinopInt(state, bits, op, rd, rn, rm, 2, 2, PSR_GE2); - emitParallelBinopInt(state, bits, op, rd, rn, rm, 3, 3, PSR_GE3); -} - -// -// Emit code for parallel add/subtract of 16-bit data -// -ARM_MORPH_FN(armEmitParallelBinop16) { - - Uns32 bits = ARM_GPR_BITS/2; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - Bool exch = state->attrs->exchange; - vmiBinop op1 = state->attrs->binop; - vmiBinop op2 = state->attrs->binop2; - vmiReg tmp = newTemp32(state); - - // save rm in temporary if exchange required and it is clobbered - if(exch && VMI_REG_EQUAL(rd, rm)) { - armEmitMoveRR(state, ARM_GPR_BITS, tmp, rm); - rm = tmp; - } - - // clear GE flags - emitClearGEFlags(state); - - // perform the parallel operations - emitParallelBinopInt(state, bits, op1, rd, rn, rm, 0, exch?2:0, PSR_GE10); - emitParallelBinopInt(state, bits, op2, rd, rn, rm, 2, exch?0:2, PSR_GE32); - - // free temporary - freeTemp32(state); -} - - -//////////////////////////////////////////////////////////////////////////////// -// PACKING, UNPACKING, SATURATION AND REVERSAL INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code for SSAT/SSAT16 -// -static void emitSSAT( - armMorphStateP state, - vmiBinop so, - Uns32 bits, - vmiReg rd, - vmiReg rn -) { - vmiReg t1 = newTemp32(state); - vmiReg tf = getTemp(state); - Uns32 shift = state->info.c; - Uns32 width = state->info.w; - vmiFlags flags = getZFFlags(tf); - vmiLabelP done = armEmitNewLabel(); - - // create bitmasks - Uns32 signMask = 1<<(width-1); - Uns32 maxMask = signMask-1; - Uns32 propMask = ~maxMask; - - // mask propMask to the operand width - if(bits!=32) { - propMask &= (1<info.c; - Uns32 width = state->info.w; - vmiLabelP done = armEmitNewLabel(); - - // create bitmasks - Uns32 maxMask = (1<info.c/8; - Uns32 delta1 = rorDelta1[dIndex]; - - // do the extension - armEmitMoveExtendRR(state, bits, t1, 8, VMI_REG_DELTA(rm,delta1), sextend); -} - -// -// Extract word into temporary with sign extension -// -static void emitExtWord( - armMorphStateP state, - vmiReg rm, - vmiReg t1, - Bool sextend -) { - Uns32 bits = ARM_GPR_BITS; - Uns32 dIndex = state->info.c/8; - Uns32 delta1 = rorDelta1[dIndex]; - - // if the word straddles the register boundary, handle it specially - if(delta1==3) { - armEmitBinopRRC(state, bits, vmi_ROR, t1, rm, 24, 0); - rm = t1; - delta1 = 0; - } - - // do the extension - armEmitMoveExtendRR(state, bits, t1, 16, VMI_REG_DELTA(rm,delta1), sextend); -} - -// -// Extract byte pair into temporaries with sign extension -// -static void emitExtBytePair( - armMorphStateP state, - vmiReg rm, - vmiReg t1, - vmiReg t2, - Bool sextend -) { - Uns32 bits = 16; - Uns32 dIndex = state->info.c/8; - Uns32 delta1 = rorDelta1[dIndex]; - Uns32 delta2 = rorDelta2[dIndex]; - - // do the extension - armEmitMoveExtendRR(state, bits, t1, 8, VMI_REG_DELTA(rm,delta1), sextend); - armEmitMoveExtendRR(state, bits, t2, 8, VMI_REG_DELTA(rm,delta2), sextend); -} - -// -// Emit code for SXTAB/UXTAB -// -static void emitXTAB(armMorphStateP state, Bool sextend) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1 = getTemp(state); - - // extract extended byte into temporary - emitExtByte(state, rm, t1, sextend); - - // create result from 32-bit addition - armEmitBinopRRR(state, bits, vmi_ADD, rd, rn, t1, 0); -} - -// -// Emit code for SXTAH/UXTAH -// -static void emitXTAH(armMorphStateP state, Bool sextend) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1 = getTemp(state); - - // extract extended word into temporary - emitExtWord(state, rm, t1, sextend); - - // create result from 32-bit addition - armEmitBinopRRR(state, bits, vmi_ADD, rd, rn, t1, 0); -} - -// -// Emit code for SXTAB16/UXTAB16 -// -static void emitXTAB16(armMorphStateP state, Bool sextend) { - - Uns32 bits = 16; - vmiReg rdL = GET_RD(state, r1); - vmiReg rnL = GET_RS(state, r2); - vmiReg rdH = VMI_REG_DELTA(rdL, 2); - vmiReg rnH = VMI_REG_DELTA(rnL, 2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1 = newTemp32(state); - vmiReg t2 = getTemp(state); - - // extract extended bytes into temporaries - emitExtBytePair(state, rm, t1, t2, sextend); - - // create result from two 16-bit additions - armEmitBinopRRR(state, bits, vmi_ADD, rdL, rnL, t1, 0); - armEmitBinopRRR(state, bits, vmi_ADD, rdH, rnH, t2, 0); - - // free temporary - freeTemp32(state); -} - -// -// Emit code for SXTB16/UXTB16 -// -static void emitXTB16(armMorphStateP state, Bool sextend) { - - Uns32 bits = 16; - vmiReg rdL = GET_RD(state, r1); - vmiReg rdH = VMI_REG_DELTA(rdL, 2); - vmiReg rm = GET_RS(state, r2); - vmiReg t1 = newTemp32(state); - vmiReg t2 = getTemp(state); - - // extract extended bytes into temporaries - emitExtBytePair(state, rm, t1, t2, sextend); - - // create result from two 16-bit moves - armEmitMoveRR(state, bits, rdL, t1); - armEmitMoveRR(state, bits, rdH, t2); - - // free temporary - freeTemp32(state); -} - -// -// Emit code for SXTB/UXTB -// -static void emitXTB(armMorphStateP state, Bool sextend) { - - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - - emitExtByte(state, rm, rd, sextend); -} - -// -// Emit code for SXTH/UXTH -// -static void emitXTH(armMorphStateP state, Bool sextend) { - - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - - emitExtWord(state, rm, rd, sextend); -} - -// -// Emit code for PKHBT -// -ARM_MORPH_FN(armEmitPKHBT) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1 = newTemp32(state); - vmiReg t2 = getTemp(state); - Uns32 shift = state->info.c; - vmiBinop so = mapShiftOp(state->info.so); - - // create lower half of the result - armEmitBinopRRC(state, bits, vmi_AND, t1, rn, 0xffff, 0); - - // create upper half of the result - armEmitBinopRRC(state, bits, so, t2, rm, shift, 0); - - // mask upper half of the result if required - if(shift<16) { - armEmitBinopRC(state, bits, vmi_AND, t2, 0xffff0000, 0); - } - - // create combined result - armEmitBinopRRR(state, bits, vmi_OR, rd, t1, t2, 0); - - // free temporary - freeTemp32(state); -} - -// -// Emit code for PKHTB -// -ARM_MORPH_FN(armEmitPKHTB) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1 = newTemp32(state); - vmiReg t2 = getTemp(state); - Uns32 shift = state->info.c; - vmiBinop so = mapShiftOp(state->info.so); - - // create upper half of the result - armEmitBinopRRC(state, bits, vmi_AND, t1, rn, 0xffff0000, 0); - - // create lower half of the result - armEmitBinopRRC(state, bits, so, t2, rm, shift, 0); - armEmitBinopRC(state, bits, vmi_AND, t2, 0xffff, 0); - - // create combined result - armEmitBinopRRR(state, bits, vmi_OR, rd, t1, t2, 0); - - // free temporary - freeTemp32(state); -} - -// -// Emit code for SSAT -// -ARM_MORPH_FN(armEmitSSAT) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop so = mapShiftOp(state->info.so); - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - - emitSSAT(state, so, bits, rd, rn); -} - -// -// Emit code for SSAT16 -// -ARM_MORPH_FN(armEmitSSAT16) { - - Uns32 bits = ARM_GPR_BITS/2; - vmiBinop so = vmi_SHR; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - - emitSSAT(state, so, bits, VMI_REG_DELTA(rd, 0), VMI_REG_DELTA(rn, 0)); - emitSSAT(state, so, bits, VMI_REG_DELTA(rd, 2), VMI_REG_DELTA(rn, 2)); -} - -// -// Emit code for USAT -// -ARM_MORPH_FN(armEmitUSAT) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop so = mapShiftOp(state->info.so); - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - - emitUSAT(state, so, bits, rd, rn); -} - -// -// Emit code for USAT16 -// -ARM_MORPH_FN(armEmitUSAT16) { - - Uns32 bits = ARM_GPR_BITS/2; - vmiBinop so = vmi_SHR; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - - emitUSAT(state, so, bits, VMI_REG_DELTA(rd, 0), VMI_REG_DELTA(rn, 0)); - emitUSAT(state, so, bits, VMI_REG_DELTA(rd, 2), VMI_REG_DELTA(rn, 2)); -} - -// -// Emit code for SXTAB -// -ARM_MORPH_FN(armEmitSXTAB) { - emitXTAB(state, True); -} - -// -// Emit code for UXTAB -// -ARM_MORPH_FN(armEmitUXTAB) { - emitXTAB(state, False); -} - -// -// Emit code for SXTAB16 -// -ARM_MORPH_FN(armEmitSXTAB16) { - emitXTAB16(state, True); -} - -// -// Emit code for UXTAB16 -// -ARM_MORPH_FN(armEmitUXTAB16) { - emitXTAB16(state, False); -} - -// -// Emit code for SXTAH -// -ARM_MORPH_FN(armEmitSXTAH) { - emitXTAH(state, True); -} - -// -// Emit code for UXTAH -// -ARM_MORPH_FN(armEmitUXTAH) { - emitXTAH(state, False); -} - -// -// Emit code for SXTB -// -ARM_MORPH_FN(armEmitSXTB) { - emitXTB(state, True); -} - -// -// Emit code for UXTB -// -ARM_MORPH_FN(armEmitUXTB) { - emitXTB(state, False); -} - -// -// Emit code for SXTB16 -// -ARM_MORPH_FN(armEmitSXTB16) { - emitXTB16(state, True); -} - -// -// Emit code for UXTB16 -// -ARM_MORPH_FN(armEmitUXTB16) { - emitXTB16(state, False); -} - -// -// Emit code for SXTH -// -ARM_MORPH_FN(armEmitSXTH) { - emitXTH(state, True); -} - -// -// Emit code for UXTH -// -ARM_MORPH_FN(armEmitUXTH) { - emitXTH(state, False); -} - -// -// Emit code for SEL -// -ARM_MORPH_FN(armEmitSEL) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1 = newTemp32(state); - vmiReg t2 = getTemp(state); - - // select GE bits from CPSR - armEmitBinopRRC(state, bits, vmi_SHR, t1, ARM_PSR, 16, 0); - armEmitBinopRC (state, bits, vmi_AND, t1, 0xf, 0); - - // convert from 0..15 to bitmask - armEmitBinopRC(state, bits, vmi_IMUL, t1, 0x00204081, 0); - armEmitBinopRC(state, bits, vmi_AND, t1, 0x01010101, 0); - armEmitBinopRC(state, bits, vmi_IMUL, t1, 0xff, 0); - - // get components from each source - armEmitBinopRRR(state, bits, vmi_AND, t2, rn, t1, 0); - armEmitBinopRRR(state, bits, vmi_ANDN, t1, rm, t1, 0); - - // assign result register - armEmitBinopRRR(state, bits, vmi_OR, rd, t1, t2, 0); - - // free temporary - freeTemp32(state); -} - -// -// Emit code for REV -// -ARM_MORPH_FN(armEmitREV) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - - armEmitUnopRR(state, bits, vmi_SWP, rd, rm, 0); -} - -// -// Emit code for REV16 -// -ARM_MORPH_FN(armEmitREV16) { - - Uns32 bits = 16; - vmiReg rdL = GET_RD(state, r1); - vmiReg rmL = GET_RS(state, r2); - vmiReg rdH = VMI_REG_DELTA(rdL, 2); - vmiReg rmH = VMI_REG_DELTA(rmL, 2); - - armEmitUnopRR(state, bits, vmi_SWP, rdL, rmL, 0); - armEmitUnopRR(state, bits, vmi_SWP, rdH, rmH, 0); -} - -// -// Emit code for REVSH -// -ARM_MORPH_FN(armEmitREVSH) { - - Uns32 bits = 16; - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - - armEmitUnopRR(state, bits, vmi_SWP, rd, rm, 0); - armEmitMoveExtendRR(state, ARM_GPR_BITS, rd, bits, rd, True); -} - -// -// This array will hold bit-reversed byte values for RBIT -// -static Uns8 rbit8[256]; - -// -// Return bit-reversed value -// -static Uns32 doRBIT(Uns32 value) { - - union {Uns32 u32; Uns8 u8[4];} u1 = {value}; - union {Uns32 u32; Uns8 u8[4];} u2; - - // generate reversed result a byte at a time using the lookup table - u2.u8[0] = rbit8[u1.u8[3]]; - u2.u8[1] = rbit8[u1.u8[2]]; - u2.u8[2] = rbit8[u1.u8[1]]; - u2.u8[3] = rbit8[u1.u8[0]]; - - // return the reversed result - return u2.u32; -} - -// -// Emit code for RBIT -// -ARM_MORPH_FN(armEmitRBIT) { - - Uns32 bits = ARM_GPR_BITS; - vmiReg rd = GET_RD(state, r1); - vmiReg rm = GET_RS(state, r2); - - static Bool init; - - // set up rbit8 table if required - if(!init) { - - Uns32 i; - - for(i=0; i<256; i++) { - - Uns8 byte = i; - Uns8 result = 0; - Uns32 j; - - for(j=0; j<8; j++) { - result = (result<<1) | (byte&1); - byte >>= 1; - } - - rbit8[i] = result; - } - - init = True; - } - - // emit embedded call to perform operation - armEmitArgReg(state, bits, rm); - armEmitCallResult(state, (vmiCallFn)doRBIT, bits, rd); -} - -//////////////////////////////////////////////////////////////////////////////// -// SIGNED MULTIPLY INSTRUCTIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code to perform dual multiply, with results in t1 and t2 -// -static void emitDualMultiply( - armMorphStateP state, - vmiReg rnL, - vmiReg rmL, - vmiReg t1, - vmiReg t2 -) { - Uns32 bits = ARM_GPR_BITS; - vmiReg rnH = VMI_REG_DELTA(rnL, 2); - vmiReg rmH = VMI_REG_DELTA(rmL, 2); - vmiReg t3 = getTemp(state); - - // exchange arguments if required - if(state->attrs->exchange) { - vmiReg tmp = rmL; rmL = rmH; rmH = tmp; - } - - // do first multiply - armEmitMoveExtendRR(state, bits, t1, 16, rnL, True); - armEmitMoveExtendRR(state, bits, t3, 16, rmL, True); - armEmitBinopRR(state, bits, vmi_IMUL, t1, t3, 0); - - // do second multiply - armEmitMoveExtendRR(state, bits, t2, 16, rnH, True); - armEmitMoveExtendRR(state, bits, t3, 16, rmH, True); - armEmitBinopRR(state, bits, vmi_IMUL, t2, t3, 0); -} - -// -// Emit code for SMLAD/SMLSD -// -ARM_MORPH_FN(armEmitSMLXD) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop op = state->attrs->binop; - vmiReg rd = GET_RD(state, r1); - vmiReg rnL = GET_RS(state, r2); - vmiReg rmL = GET_RS(state, r3); - vmiReg ra = GET_RS(state, r4); - vmiReg t1 = newTemp32(state); - vmiReg t2 = newTemp32(state); - - // do dual multiply, results in t1 and t2 - emitDualMultiply(state, rnL, rmL, t1, t2); - - // combine results, setting CPSR.Q if overflow (ADD only, special case of - // 0x8000*0x8000 + 0x8000*0x8000) - if(op==vmi_ADD) { - emitOpSetQ(state, bits, op, t1, t1, t2); - } else { - armEmitBinopRR(state, bits, op, t1, t2, 0); - } - - // accumulate, setting CPSR.Q if overflow - emitOpSetQ(state, bits, vmi_ADD, rd, ra, t1); - - // free temporaries - freeTemp32(state); - freeTemp32(state); -} - -// -// Emit code for SMUAD/SMUSD -// -ARM_MORPH_FN(armEmitSMUXD) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop op = state->attrs->binop; - vmiReg rd = GET_RD(state, r1); - vmiReg rnL = GET_RS(state, r2); - vmiReg rmL = GET_RS(state, r3); - vmiReg t1 = newTemp32(state); - vmiReg t2 = newTemp32(state); - - // do dual multiply, results in t1 and t2 - emitDualMultiply(state, rnL, rmL, t1, t2); - - // generate result, setting CPSR.Q if overflow (ADD only) - if(op==vmi_ADD) { - emitOpSetQ(state, bits, op, rd, t1, t2); - } else { - armEmitBinopRRR(state, bits, op, rd, t1, t2, 0); - } - - // free temporaries - freeTemp32(state); - freeTemp32(state); -} - -// -// Emit code for SMLALD/SMLSLD -// -ARM_MORPH_FN(armEmitSMLXLD) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop op = state->attrs->binop; - vmiReg rdLo = GET_RD(state, r1); - vmiReg rdHi = GET_RD(state, r2); - vmiReg rnL = GET_RS(state, r3); - vmiReg rmL = GET_RS(state, r4); - vmiReg t1 = newTemp64(state); - vmiReg t2 = newTemp32(state); - vmiReg tf = t2; - vmiFlags flags = getCFFlags(tf); - - // do dual multiply, results in t1 and t2 - emitDualMultiply(state, rnL, rmL, t1, t2); - - // extend results to 64 bits - armEmitMoveExtendRR(state, 64, t1, bits, t1, True); - armEmitMoveExtendRR(state, 64, t2, bits, t2, True); - - // add/subtract extended results - armEmitBinopRR(state, 64, op, t1, t2, 0); - - // add total to accumulator - armEmitBinopRR(state, bits, vmi_ADD, rdLo, VMI_REG_DELTA(t1, 0), &flags); - armEmitBinopRR(state, bits, vmi_ADC, rdHi, VMI_REG_DELTA(t1, 4), &flags); - - // free temporaries - freeTemp32(state); - freeTemp64(state); -} - -// -// Emit code for SMMLX -// -ARM_MORPH_FN(armEmitSMMLX) { - - Uns32 bits = ARM_GPR_BITS; - vmiBinop op = state->attrs->binop; - vmiReg rd = GET_RD(state, r1); - vmiReg rn = GET_RS(state, r2); - vmiReg rm = GET_RS(state, r3); - vmiReg t1L = newTemp64(state); - vmiReg t1H = VMI_REG_DELTA(t1L, 4); - - // do the multiply - armEmitMulopRRR(state, bits, vmi_IMUL, t1H, t1L, rn, rm, 0); - - // accumulate if required - if(state->attrs->accumulate) { - - vmiReg t2L = getTemp(state); - vmiReg t2H = VMI_REG_DELTA(t2L, 4); - - armEmitMoveRC(state, bits, t2L, 0); - armEmitMoveRR(state, bits, t2H, GET_RS(state, r4)); - - armEmitBinopRR(state, 64, op, t1L, t2L, 0); - } - - // round if required - if(state->attrs->round) { - armEmitBinopRC(state, 64, vmi_ADD, t1L, 0x80000000, 0); - } - - // assign to result - armEmitMoveRR(state, bits, rd, t1H); - - // free temporary - freeTemp64(state); -} - -//////////////////////////////////////////////////////////////////////////////// -// VFP Utility functions -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit NOCP Usage Fault if FPU is disabled -// -#define VFP_DISABLED(_S) emitUsageFault(state, EXC_UNDEF_NOCP); return False; - -// -// This is the ARM CheckVFPEnabled psuedo-code primitive -// -static Bool checkVFPEnabled(armMorphStateP state) { - - armP arm = state->arm; - Bool inUserMode = IN_USER_MODE(arm); - Uns32 cp10Enable = SCS_FIELD(arm, CPACR, cp10); - - // this code block is dependent on the enable state of coprocessor 10 - armEmitValidateBlockMask(ARM_BM_CP10); - - // check CPACR for permission to use cp10 (and cp11) in the current user/privilege mode - if(inUserMode && !(cp10Enable&2)) { - VFP_DISABLED(state); - } else if(!inUserMode && !(cp10Enable&1)) { - VFP_DISABLED(state); - } - - return True; -} - -// -// This is the ARM ExecuteFPCheck primitive -// -static Bool executeFPCheck(armMorphStateP state) { - - armP arm = state->arm; - - VMI_ASSERT(FPU_PRESENT(arm), "FP instruction when no FPU present"); - - if (!checkVFPEnabled(state)) { - - // Access to CP10 not enabled - return False; - - } else { - - Bool endMorphBlock = False; - - // this code block is dependent on the CONTROL.FPCA, FPCCR.ASPEN and FPCCR.LSPACT bits - armEmitValidateBlockMask(ARM_BM_FPCA|ARM_BM_ASPEN|ARM_BM_LSPACT); - - // If FP lazy context save is enabled then save state - if (SCS_FIELD(arm, FPCCR, LSPACT)) { - - // Preserve the FP state in the saved stack space - armEmitArgProcessor(state); - armEmitCall(state, (vmiCallFn)armPreserveFPState); - - // preserveFPState will clear LSPACT so should end block - endMorphBlock = True; - } - - // If ASPEN is on then check is FPCA is off. If it is, then this is the - // first FP instruction in this context - if (SCS_FIELD(arm, FPCCR, ASPEN) && !CONTROL_FIELD(arm, FPCA)) { - - Uns32 bits = ARM_GPR_BITS; - - // copy FPDSCR values to FPSCR - armEmitArgProcessor(state); - armEmitArgReg(state, bits, ARM_SCS_REG(SCS_ID(FPDSCR))); - armEmitArgUns32(state, SCS_WRITE_MASK_FPDSCR); - armEmitCall(state, (vmiCallFn)armWriteFPSCR); - - // Set CONTROL.FPCA bit - armEmitBinopRC(state, 32, vmi_OR, ARM_CONTROL, CONTROL_FPCA, 0); - - // CONTROL.FPCA has changed so should end block - endMorphBlock = True; - } - - if (endMorphBlock) { - // terminate the code block (CONTROL.FPCA or FPCCR.LSPACT has changed) - armEmitEndBlock(); - } - } - - // VFP is available - return True; - -} - -// -// Load the Flt64 register with the floating point constant value of 2^n -// -static vmiReg getFPConstPower2Flt64(armMorphStateP state, Uns32 n) { - - Uns64 twoN = (1ULL << n); - vmiReg r = newTemp64(state); - - union {Flt64 f64; Uns64 u64;} u = {f64:twoN}; - - armEmitMoveRC(state, 64, r, u.u64); - - return r; -} - -// -// Load the Flt80 register with the floating point constant value of 2^n -// -static vmiReg getFPConstPower2Flt80(armMorphStateP state, Uns32 n) { - - Uns64 twoN = (1ULL << n); - vmiReg r = newTemp128(state); - - union {Flt80 f80; Uns64 u64; Uns16 u16[8];} u = {f80:twoN}; - - armEmitMoveRC(state, 64, r, u.u64); - armEmitMoveRC(state, 16, VMI_REG_DELTA(r, 8), u.u16[4]); - - return r; -} - -// -// Get floating point operation type for ARM integer type from size of operand in bytes -// -static vmiFType bytesToIType(Uns32 ebytes, Bool isSigned) { - switch(ebytes) { - case 2: - return isSigned ? vmi_FT_16_INT : vmi_FT_16_UNS; - case 4: - return isSigned ? vmi_FT_32_INT : vmi_FT_32_UNS; - default: - VMI_ABORT("%s: unimplemented size for floating point type: %d bytes", FUNC_NAME, ebytes); - return 0; // Not reached - } -} - -// -// Get floating point operation type for ARM floating point type from size of operand in bytes -// -static vmiFType bytesToFType(Uns32 ebytes) { - switch(ebytes) { - case 4: - return vmi_FT_32_IEEE_754; - case 8: - return vmi_FT_64_IEEE_754; - default: - VMI_ABORT("%s: unimplemented size for floating point type: %d bytes", FUNC_NAME, ebytes); - return 0; // Not reached - } -} - - -// -// This is FPNeg from psuedo-code -// Negate the value in the register by toggling the sign bit -// -static void FPNeg(armMorphStateP state, vmiReg dest, vmiReg src, Uns32 size) { - - Uns64 signBit = 1ULL << (size-1); - - armEmitBinopRRC(state, size, vmi_XOR, dest, src, signBit, 0); -} - -// -// This is FixedToFP from psuedo-code -// Note: fpscr_controlled selection is done automatically in armEmit... call -// -static void fixedToFP( - armMorphStateP state, - vmiReg result, - Uns32 resultBytes, - vmiReg operand, - Uns32 operandBytes, - Uns32 fracBits, - Bool isSigned, - Bool roundToNearest -) { - vmiFPRC round = roundToNearest ? vmi_FPR_NEAREST : vmi_FPR_CURRENT; - vmiFType operandType = bytesToIType(operandBytes, isSigned); - - VMI_ASSERT(operandBytes==4 || operandBytes==2, "operand size in bytes %d must be 2 or 4", operandBytes); - VMI_ASSERT(fracBits <= operandBytes*8, "fracBits = %d must be <= %d", fracBits, operandBytes*8); - - if (fracBits) { - - // Fixed point to floating point - must scale by fracBits - Bool singlePrec = (resultBytes == 4); - vmiReg t = newTemp64(state); - vmiReg power2 = getFPConstPower2Flt64(state, fracBits); - - // Convert integer to double precision floating point (rounding mode unused here) - armEmitFConvertRR(state, vmi_FT_64_IEEE_754, t, operandType, operand, vmi_FPR_CURRENT); - - if (singlePrec) { - - // Get result / 2^fracBits (always exact, so no rounding) - armEmitFBinopSimdRRR(state, vmi_FT_64_IEEE_754, 1, vmi_FDIV, t, t, power2); - - // Convert to single precision (may be rounded) - armEmitFConvertRR(state, vmi_FT_32_IEEE_754, result, vmi_FT_64_IEEE_754, t, round); - - } else { - - // result = value / 2^fracBits (always exact, so no rounding) - armEmitFBinopSimdRRR(state, vmi_FT_64_IEEE_754, 1, vmi_FDIV, result, t, power2); - } - - } else { - - // Just convert integer to target floating point type (may be rounded) - vmiFType resultType = bytesToFType(resultBytes); - - armEmitFConvertRR(state, resultType, result, operandType, operand, round); - } -} - -// -// This is FPToFixed from psuedo-code -// Note: fpscr_controlled selection is done automatically in armEmit... call -// -static void FPToFixed ( - armMorphStateP state, - vmiReg result, - Uns32 resultBytes, - vmiReg operand, - Uns32 operandBytes, - Uns32 fracBits, - Bool isSigned, - Bool roundTowardsZero -) { - vmiFPRC round = roundTowardsZero ? vmi_FPR_ZERO : vmi_FPR_CURRENT; - vmiFType opType = bytesToFType(operandBytes); - - VMI_ASSERT(operandBytes==4 || operandBytes==8, "operand size in bytes %d must be 8 or 4", operandBytes); - VMI_ASSERT(resultBytes==4 || resultBytes==2, "result size in bytes %d must be 2 or 4", resultBytes); - VMI_ASSERT(fracBits <= resultBytes*8, "fracBits = %d must be <= %d", fracBits, resultBytes*8); - - if (fracBits) { - - // Scale by fracBits - vmiReg power2 = getFPConstPower2Flt80(state, fracBits); - vmiReg t = newTemp128(state); - - // Convert operand to 80 bit fp value (rounding mode unused here) - armEmitFConvertRR(state, vmi_FT_80_X87, t, opType, operand, vmi_FPR_CURRENT); - - // t = t * 2^fracBits (always bigger, so no rounding) - armEmitFBinopSimdRRR(state, vmi_FT_80_X87, 1, vmi_FMUL, t, t, power2); - - // Use temporary as operand source - opType = vmi_FT_80_X87; - operand = t; - } - - // convert to required type - vmiFType resultType = bytesToIType(resultBytes, isSigned); - armEmitFConvertRR(state, resultType, result, opType, operand, round); -} - -// -// Set FPSCR flags according to the vmiFPRelation value -// -static void setFPSCRFlags(armP arm, vmiFPRelation relation) { - - if (relation == vmi_FPRL_UNORDERED) { - arm->sdfpAFlags.ZF = arm->sdfpAFlags.NF = 0; - arm->sdfpAFlags.CF = arm->sdfpAFlags.VF = 1; - } else if (relation == vmi_FPRL_EQUAL) { - arm->sdfpAFlags.NF = arm->sdfpAFlags.VF = 0; - arm->sdfpAFlags.ZF = arm->sdfpAFlags.CF = 1; - } else if (relation == vmi_FPRL_LESS) { - arm->sdfpAFlags.ZF = arm->sdfpAFlags.CF= arm->sdfpAFlags.VF = 0; - arm->sdfpAFlags.NF = 1; - } else if (relation == vmi_FPRL_GREATER) { - arm->sdfpAFlags.ZF = arm->sdfpAFlags.NF= arm->sdfpAFlags.VF = 0; - arm->sdfpAFlags.CF = 1; - } else { - VMI_ABORT("unsupported fp relation result 0x%x", relation); - } - -} - -// -// Assign APSR VCMPflags from FPSCR flags -// -static void getFPSCRFlags(armP arm) { - - arm->aflags = arm->sdfpAFlags; - -} - -//////////////////////////////////////////////////////////////////////////////// -// VFP VLD and VST -//////////////////////////////////////////////////////////////////////////////// - -// -// Callback function for V load/store -// -#define V_LOAD_STORE_FN(_NAME) void _NAME( \ - armMorphStateP state, \ - Uns32 memBits, \ - vmiReg base, \ - Int32 offset, \ - vmiReg rd \ -) -typedef V_LOAD_STORE_FN((*VLoadStoreFn)); - - -// -// Swap rdH and rd if endian is big -// -static inline void endianSwapRegs(armMorphStateP state, vmiReg *rdH, vmiReg *rd) { - - memEndian endian = armGetEndian((vmiProcessorP)state->arm, False); - - if (endian == MEM_ENDIAN_BIG) { - - vmiReg t; - - t = *rdH; - *rdH = *rd; - *rd = t; - } -} - -// -// Emit code to load a VFP register from memory address [base]+offset -// -static V_LOAD_STORE_FN(emitVLoad) { - - if (memBits == 2*ARM_GPR_BITS) { - - vmiReg rdH = getR64Hi(rd); - - endianSwapRegs(state, &rdH, &rd); - armEmitLoadRRRO(state, memBits, offset, rd, rdH, base, getTemp(state), False, False); - - } else if (memBits <= ARM_GPR_BITS) { - - armEmitLoadRRO(state, memBits, offset, rd, base, False, False); - - } else { - - VMI_ABORT("Invalid memBits %d", memBits); - - } -} - -// -// Emit code to store a VFP register to memory address [base]+offset -// When double word register adjust register depending on endian -// -static V_LOAD_STORE_FN(emitVStore) { - - if (memBits == 2*ARM_GPR_BITS) { - - vmiReg rdH = getR64Hi(rd); - - endianSwapRegs(state, &rdH, &rd); - armEmitStoreRRRO(state, memBits, offset, base, rd, rdH); - - } else if (memBits <= ARM_GPR_BITS) { - - armEmitStoreRRO(state, memBits, offset, base, rd); - - } else { - - VMI_ABORT("Invalid memBits %d", memBits); - - } -} - - -// -// Common code for a VLDR or VSTR instruction -// -static void emitVLoadStore(armMorphStateP state, VLoadStoreFn cb, Bool isLoad) { - - if(executeFPCheck(state)) { - - Uns32 ebytes = state->attrs->ebytes; - Uns32 memBits = ebytes*8; - vmiReg rd = GET_VFP_REG(state, r1, ebytes); - vmiReg base = GET_RS(state, r2); - Int32 offset = state->info.c; - if (isLoad) { - - // For loads only: align the constant if the base register is the - // program counter (has effect for PC-relative Thumb load instructions only) - if(VMI_REG_EQUAL(base, ARM_PC)) { - offset = alignConstWithPC(state, offset); - } - - } - - (*cb) (state, memBits, base, offset, rd); - - } -} - -// -// Emit code for VLDR S or D, [RN, #imm] -// -ARM_MORPH_FN(armEmitVLDR) { - emitVLoadStore(state, emitVLoad, True); -} - -// -// Emit code for VLDR S or D, [RN, #imm] -// -ARM_MORPH_FN(armEmitVSTR) { - emitVLoadStore(state, emitVStore, False); -} - -// -// Common code for Load or Store Multiple using the passed call back function -// -static void emitVLoadStoreM(armMorphStateP state, VLoadStoreFn cb) { - - if(executeFPCheck(state)) { - - Uns32 ebytes = state->attrs->ebytes; - Uns32 memBits = ebytes*8; - vmiReg base = GET_RS(state, r1); - Uns32 nregs = state->info.nregs; - Bool increment = doIncrement(state); - Uns32 frameSize = nregs * ebytes; - Int32 frameDelta = increment ? frameSize : -frameSize; - Int32 offset = increment ? 0 : -frameSize; - Int32 stepBefore = getStepBefore(state, ebytes); - Int32 stepAfter = getStepAfter (state, ebytes); - Uns32 r; - - // load or store registers - for(r=0; rinfo.wb) { - - armEmitBinopRC(state, ARM_GPR_BITS, vmi_ADD, base, frameDelta, 0); - - } - } -} - -// -// Emit code for VLDM RN{!}, -// -ARM_MORPH_FN(armEmitVLDM) { - emitVLoadStoreM(state, emitVLoad); -} - -// -// Emit code for VSTM RN{!}, -// -ARM_MORPH_FN(armEmitVSTM) { - emitVLoadStoreM(state, emitVStore); -} - -//////////////////////////////////////////////////////////////////////////////// -// VFP VMOV, etc instructions -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code for VMRS -// -ARM_MORPH_FN(armEmitVMRS) { - - Uns32 bits = ARM_GPR_BITS; - - // FPSCR is accessible if cp10/11 access is enabled - if(!executeFPCheck(state)) { - // no action - } else if(state->info.r1==ARM_REG_PC) { - // assign CPSR flags from FPSCR flags - armEmitArgProcessor(state); - armEmitCall(state, (vmiCallFn)getFPSCRFlags); - - // terminate the code block (derived flags are invalid) - armEmitEndBlock(); - } else { - vmiReg rd = GET_RD(state, r1); - - armEmitArgProcessor(state); - armEmitCallResult(state, (vmiCallFn)armReadFPSCR, bits, rd); - } -} - -// -// Emit code for VMSR -// -ARM_MORPH_FN(armEmitVMSR) { - - Uns32 bits = ARM_GPR_BITS; - - // FPSCR is accessible in user mode - if(executeFPCheck(state)) { - armEmitArgProcessor(state); - armEmitArgReg(state, bits, GET_RS(state, r1)); - armEmitArgUns32(state, FPSCR_MASK); - armEmitCall(state, (vmiCallFn)armWriteFPSCR); - - // terminate the code block (block masks or floating point - // mode may have changed) - armEmitEndBlock(); - } -} - -// -// Emit code for VMOV.F32 Sd, Sm -// -ARM_MORPH_FN(armEmitVMOVR_VFP) { - - if(executeFPCheck(state)) { - - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rs = GET_VFP_SREG(state, r2); - - armEmitMoveRR(state, 32, rd, rs); - } -} - -// -// Emit code for VMOV.F32 Sd, # or VMOV.F64 Dd, # -// -ARM_MORPH_FN(armEmitVMOVI_VFP) { - - if(executeFPCheck(state)) { - - vmiReg rd = GET_VFP_SREG(state, r1); - Uns64 mi = state->info.sdfpMI.u64; - - armEmitMoveRC(state, 32, rd, mi); - } -} - -// -// Emit code for VMOV RT, SN -// -ARM_MORPH_FN(armEmitVMOVRS) { - - if(executeFPCheck(state)) { - - vmiReg rd = GET_RD(state, r1); - vmiReg rs = GET_VFP_SREG(state, r2); - - armEmitMoveRR(state, ARM_GPR_BITS, rd, rs); - } -} - -// -// Emit code for VMOV SN, RT -// -ARM_MORPH_FN(armEmitVMOVSR) { - - if(executeFPCheck(state)) { - - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rs = GET_RS(state, r2); - - armEmitMoveRR(state, ARM_GPR_BITS, rd, rs); - } -} - -// -// Emit code for VMOV RT, RT2, DN -// -ARM_MORPH_FN(armEmitVMOVRRD) { - - if(executeFPCheck(state)) { - - vmiReg rdL = GET_RD(state, r1); - vmiReg rdH = GET_RD(state, r2); - vmiReg rsL = GET_VFP_DREG(state, r3); - vmiReg rsH = getR64Hi(rsL); - - armEmitMoveRR(state, ARM_GPR_BITS, rdL, rsL); - armEmitMoveRR(state, ARM_GPR_BITS, rdH, rsH); - } -} - -// -// Emit code for VMOV DN, RT, RT2 -// -ARM_MORPH_FN(armEmitVMOVDRR) { - - if(executeFPCheck(state)) { - - vmiReg rdL = GET_VFP_DREG(state, r1); - vmiReg rdH = getR64Hi(rdL); - vmiReg rsL = GET_RS(state, r2); - vmiReg rsH = GET_RS(state, r3); - - armEmitMoveRR(state, ARM_GPR_BITS, rdL, rsL); - armEmitMoveRR(state, ARM_GPR_BITS, rdH, rsH); - } -} - -// -// Emit code for VMOV RT, RT2, SM, SM1 -// -ARM_MORPH_FN(armEmitVMOVRRSS) { - - if(executeFPCheck(state)) { - - vmiReg rdL = GET_RD(state, r1); - vmiReg rdH = GET_RD(state, r2); - vmiReg rsL = GET_VFP_SREG(state, r3); - vmiReg rsH = GET_VFP_SREG(state, r3+1); - - armEmitMoveRR(state, ARM_GPR_BITS, rdL, rsL); - armEmitMoveRR(state, ARM_GPR_BITS, rdH, rsH); - } -} - -// -// Emit code for VMOV SM, SM1, RT, RT2 -// -ARM_MORPH_FN(armEmitVMOVSSRR) { - - if(executeFPCheck(state)) { - - vmiReg rdL = GET_VFP_SREG(state, r1); - vmiReg rdH = GET_VFP_SREG(state, r1+1); - vmiReg rsL = GET_RS(state, r2); - vmiReg rsH = GET_RS(state, r3); - - armEmitMoveRR(state, ARM_GPR_BITS, rdL, rsL); - armEmitMoveRR(state, ARM_GPR_BITS, rdH, rsH); - } -} - -// -// Emit code for VMOV DD[x], RT -// -ARM_MORPH_FN(armEmitVMOVZR) { - - if(executeFPCheck(state)) { - - Uns32 index = state->info.index; - vmiReg rd = GET_VFP_SCALAR(state, r1, index); - vmiReg rs = GET_RS(state, r2); - - armEmitMoveRR(state, ARM_GPR_BITS, rd, rs); - } -} - -// -// Emit code for VMOV RT, DD[x] -// -ARM_MORPH_FN(armEmitVMOVRZ) { - - if(executeFPCheck(state)) { - - Uns32 index = state->info.index; - vmiReg rd = GET_RS(state, r1); - vmiReg rs = GET_VFP_SCALAR(state, r2, index); - - armEmitMoveRR(state, ARM_GPR_BITS, rd, rs); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// VFP Data-Processing Instructions -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code for VFP single precision floating point , with 3 regs -// -ARM_MORPH_FN(armEmitVFPBinop) { - - if(executeFPCheck(state)) { - - vmiReg r1 = GET_VFP_SREG(state, r1); - vmiReg r2 = GET_VFP_SREG(state, r2); - vmiReg r3 = GET_VFP_SREG(state, r3); - vmiFBinop op = state->attrs->fbinop; - Bool negate = state->attrs->negate; - - armEmitFBinopSimdRRR(state, vmi_FT_32_IEEE_754, 1, op, r1, r2, r3); - - // If negate attribute is selected negate the result - if (negate) FPNeg(state, r1, r1, 32); - } -} - -// -// Emit code for single precision VFP floating point , with 2 regs -// -ARM_MORPH_FN(armEmitVFPUnop) { - - if(executeFPCheck(state)) { - - vmiReg r1 = GET_VFP_SREG(state, r1); - vmiReg r2 = GET_VFP_SREG(state, r2); - vmiFBinop op = state->attrs->funop; - - armEmitFUnopSimdRR(state, vmi_FT_32_IEEE_754, 1, op, r1, r2); - - } -} - -// -// Emit code for VFP VABS Sd, Sm -// Simply mask off sign bit -// -ARM_MORPH_FN(armEmitVABS_VFP) { - - if(executeFPCheck(state)) { - - vmiReg r1 = GET_VFP_SREG(state, r1); - vmiReg r2 = GET_VFP_SREG(state, r2); - - armEmitBinopRRC(state, 32, vmi_ANDN, r1, r2, 0x80000000, 0); - - } -} - -// -// Emit code for VFP VNEG Sd, Sm or VNEG Dd, Dm -// -ARM_MORPH_FN(armEmitVNEG_VFP) { - - if(executeFPCheck(state)) { - - vmiReg r1 = GET_VFP_SREG(state, r1); - vmiReg r2 = GET_VFP_SREG(state, r2); - - // Take negative value by simply toggling the sign bit - FPNeg(state, r1, r2, 32); - - } -} - -// -// Emit code for VFP floating point Multiply (negate) accumulate/subtract instruction -// -ARM_MORPH_FN(armEmitVMulAcc_VFP) { - - if(executeFPCheck(state)) { - - vmiReg r1 = GET_VFP_SREG(state, r1); - vmiReg r2 = GET_VFP_SREG(state, r2); - vmiReg r3 = GET_VFP_SREG(state, r3); - vmiFBinop op = state->attrs->fbinop; - Bool negate = state->attrs->negate; - vmiReg product = newTemp32(state); - vmiReg acc = r1; - - VMI_ASSERT(op==vmi_FSUB || op==vmi_FADD, "Invalid fbinop"); - - // Perform Multiply to temporary - armEmitFBinopSimdRRR(state, vmi_FT_32_IEEE_754, 1, vmi_FMUL, product, r2, r3); - - if (negate) { - - // Negate the accumulation value before adding/subtracting - acc = newTemp64(state); - FPNeg(state, acc, r1, 32); - - } - - // To implement subtraction, negate the value being subtracted and use vmi_FADD - if (op == vmi_FSUB) FPNeg(state, product, product, 32); - - // Add the (possibly negated) product to/from the accumlate value (+/- r1) - armEmitFBinopSimdRRR(state, vmi_FT_32_IEEE_754, 1, vmi_FADD, r1, acc, product); - } -} - -// -// Emit code for VFP single precision fused multiply accumulate -// -ARM_MORPH_FN(armEmitVFusedMAC) { - - if(executeFPCheck(state)) { - - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg addend = rd; - vmiReg op1 = GET_VFP_SREG(state, r2); - vmiReg op2 = GET_VFP_SREG(state, r3); - Bool negate = state->attrs->negate; - Bool subtract = state->attrs->subtract; - - if (subtract) { - // Use negative of op1 - vmiReg t = newTemp32(state); - FPNeg(state, t, op1, 32); - op1 = t; - } - - if (negate) { - // Use negative of r1 as addend - vmiReg t = newTemp32(state); - FPNeg(state, t, addend, 32); - addend = t; - } - - // Do rd = addend + (op1 * op2) with no rounding of intermediate results - armEmitFTernopSimdRRRR(state, vmi_FT_32_IEEE_754, 1, vmi_FMADD, rd, op1, op2, addend, False); - - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// VFP VCMP Instructions -//////////////////////////////////////////////////////////////////////////////// - -// -// Common code to execute VFP VCMP instructions -// -static void emitVCmpVFP(armMorphStateP state, vmiReg rd, vmiReg rm) { - - Bool allowQNaN = state->attrs->allowQNaN; - vmiReg relation = getTemp(state); - - // Compare the floating point operands, getting vmiFPRelation result in the register relation - armEmitFCompareRR(state, vmi_FT_32_IEEE_754, relation, rd, rm, allowQNaN, True); - - // Set the FPSCR N, Z, C, V flags according to the result - armEmitArgProcessor(state); - armEmitArgReg(state, 8, relation); - armEmitCall(state, (vmiCallFn) setFPSCRFlags); - -} - -// -// Emit code for VFP VCMP/VCMPE instruction: VCMP{E} Sd, Sm -// -ARM_MORPH_FN(armEmitVCMP_VFP) { - - if(executeFPCheck(state)) { - - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rm = GET_VFP_SREG(state, r2); - - emitVCmpVFP(state, rd, rm); - - } -} - -// -// Emit code for VFP VCMP/VCMPE immediate 0.0 instruction: VCMP{E} Sd, #0.0 -// Note: VCMP instruction does not use short vectors -// -ARM_MORPH_FN(armEmitVCMP0_VFP) { - - if(executeFPCheck(state)) { - - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rm = newTemp32(state); - - armEmitMoveRC(state, 32, rm, 0); - emitVCmpVFP(state, rd, rm); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// VFP VCVT Instructions -//////////////////////////////////////////////////////////////////////////////// - -// -// Emit code for VFP Half to Single precision conversion: VCVTT.F32.F16 Sd, Sm or VCVTB.F32.F16 Sd, Sm -// -ARM_MORPH_FN(armEmitVCVT_SH_VFP) { - - if(executeFPCheck(state)) { - - Uns32 top = state->attrs->highhalf ? 1 : 0; - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rm = GET_VFP_SREG(state, r2); - - // point to top half of register when VCVTT - if (top) rm = VMI_REG_DELTA(rm, 2); - - armEmitArgProcessor(state); // argument 1: processor - armEmitArgReg(state, 16, rm); // argument 2: value in rm - armEmitCallResult(state, (vmiCallFn)armFPHalfToSingle, 32, rd); - } -} - -// -// Emit code for VFP Single to Half precision conversion: VCVTT.F16.F32 Sd, Sm or VCVTB.F16.F32 Sd, Sm -// -ARM_MORPH_FN(armEmitVCVT_HS_VFP) { - - if(executeFPCheck(state)) { - - Uns32 top = state->attrs->highhalf ? 1 : 0; - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rm = GET_VFP_SREG(state, r2); - - // point to top half of register when VCVTT - if (top) rd = VMI_REG_DELTA(rd, 2); - - armEmitArgProcessor(state); // argument 1: processor - armEmitArgReg(state, 32, rm);// argument 2: value - armEmitCallResult(state, (vmiCallFn)armFPSingleToHalf, 16, rd); - } -} - -// -// Emit code for VFP single precision Floating point to Fixed point (32 or 16 bit) conversion: VCVT -// Note: r1 always equals r2 and the size of the fixed point value is defined by ebytes -// Note: sextend indicates if 16 bit result should be sign extended -// Note: roundFPSCR indicates if the normal rounding mode or round to nearest mode is used -// -ARM_MORPH_FN(armEmitVCVT_XF_VFP) { - - if(executeFPCheck(state)) { - - VMI_ASSERT(state->info.r1== state->info.r2, "r1 must be same as r2"); - - Uns32 fracBits = state->info.c; - Uns32 sextend = state->attrs->sextend; - vmiFPRC roundFPSCR = state->attrs->roundFPSCR; - Uns32 fxBytes = state->attrs->ebytes; - vmiReg rd = GET_VFP_SREG(state, r1); - - FPToFixed(state, rd, fxBytes, rd, 4, fracBits, sextend, !roundFPSCR); - - if (fxBytes != 4) { - // sign extend to fill destination registeru - armEmitMoveExtendRR(state, 32, rd, fxBytes*8, rd, sextend); - } - } -} - -// -// Emit code for VFP single precsion Floating point to signed or unsigned 32 bit Integer conversion: VCVT -// -ARM_MORPH_FN(armEmitVCVT_IF_VFP) { - - if(executeFPCheck(state)) { - - Uns32 sextend = state->attrs->sextend; - vmiFPRC roundFPSCR = state->attrs->roundFPSCR; - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rm = GET_VFP_SREG(state, r2); - - FPToFixed(state, rd, 4, rm, 4, 0, sextend, !roundFPSCR); - } -} - -// -// Emit code for VFP Fixed point to single precision Floating point conversion: VCVT -// Note: r1 always equals r2 and the size of the fixed point value is defined by ebytes -// -ARM_MORPH_FN(armEmitVCVT_FX_VFP) { - - if(executeFPCheck(state)) { - - VMI_ASSERT(state->info.r1== state->info.r2, "r1 must be same as r2"); - - Uns32 fracBits = state->info.c; - Uns32 sextend = state->attrs->sextend; - vmiFPRC roundFPSCR = state->attrs->roundFPSCR; - Uns32 fxBytes = state->attrs->ebytes; - vmiReg rd = GET_VFP_SREG(state, r1); - - fixedToFP(state, rd, 4, rd, fxBytes, fracBits, sextend, !roundFPSCR); - } -} - -// -// Emit code for VFP Integer to single precision Floating point conversion: VCVT -// -ARM_MORPH_FN(armEmitVCVT_FI_VFP) { - - if(executeFPCheck(state)) { - - Uns32 sextend = state->attrs->sextend; - vmiFPRC roundFPSCR = state->attrs->roundFPSCR; - vmiReg rd = GET_VFP_SREG(state, r1); - vmiReg rm = GET_VFP_SREG(state, r2); - - fixedToFP(state, rd, 4, rm, 4, 0, sextend, !roundFPSCR); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// DEPRECATED DISASSEMBLY MODE -//////////////////////////////////////////////////////////////////////////////// - -// -// Disassembly mode: SWI 99/9999 terminates the test -// -#define ARM_SWI_EXIT_CODE_THUMB 99 -#define ARM_SWI_EXIT_CODE_NORMAL 9999 - -// -// Should morphing be disabled? (disassembly test mode only) -// -static Bool disableMorph(armMorphStateP state) { - - armP arm = state->arm; - - if(!ARM_DISASSEMBLE(arm)) { - return False; - } else if(state->info.type!=ARM_IT_SWI) { - return True; - } else if( - ( IN_THUMB_MODE(arm) && (state->info.c==ARM_SWI_EXIT_CODE_THUMB)) || - (!IN_THUMB_MODE(arm) && (state->info.c==ARM_SWI_EXIT_CODE_NORMAL)) - ) { - armEmitExit(); - return True; - } else { - return True; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// MORPHER MAIN ROUTINES -//////////////////////////////////////////////////////////////////////////////// - -// -// Advance to the new IT state -// -static Uns8 itAdvance(Uns8 oldState) { - Uns8 newState = (oldState & 0xe0) | ((oldState<<1) & 0x1f); - return (newState & 0xf) ? newState : 0; -} - -// -// Emit code to update ITSTATE if required when the instruction completes (note -// that jumps and branches take special action to reset ITSTATE elsewhere) -// -static void emitUpdateITState(armMorphStateP state) { - - armP arm = state->arm; - - if(state->info.it) { - arm->itStateMT = state->info.it; - armEmitMoveRC(state, 8, ARM_IT_STATE, arm->itStateMT); - } else if(arm->itStateMT) { - arm->itStateMT = itAdvance(arm->itStateMT); - armEmitMoveRC(state, 8, ARM_IT_STATE, arm->itStateMT); - } -} - -// -// Default morpher callback for implemented instructions -// -static void emitImplemented(armMorphStateP state) { - - // start code to skip this instruction conditionally unless it can be - // emitted as a conditional jump - setSkipLabel(state, !state->attrs->condJump ? emitStartSkip(state) : 0); - - // generate instruction code - state->attrs->morphCB(state); - - // generate implicit jump to next instruction if required - armEmitImplicitUncondJump(state); - - // insert conditional instruction skip target label - emitLabel(getSkipLabel(state)); - - // update ITSTATE if required when the instruction completes - emitUpdateITState(state); -} - -// -// Check whether the VFP floating-point type is not supported at the minimum required level -// -static Bool supportVFP(armMorphStateP state, armSDFPType dt, Uns32 minLevel) { - - armP arm = state->arm; - Bool ok; - - VMI_ASSERT (state->attrs->iType==ARM_TY_VFP, "Called with non-VFP instruction"); - - if (!FPU_PRESENT(state->arm)) { - ok = False; - } else if (dt == ARM_SDFPT_F32) { - ok = SCS_FIELD(arm, MVFR0, SinglePrecision) >= minLevel; - } else if (dt == ARM_SDFPT_F64) { - ok = SCS_FIELD(arm, MVFR0, DoublePrecision) >= minLevel; - } else { - ok = True; - } - - return ok; -} - -// -// Determine whether a feature is supported by ISAR -// -static Bool supportedByISAR(armP arm, armMorphStateP state) { - switch(state->info.isar) { - case ARM_ISAR_DIV: - return ARM_ISAR(0, Divide_instrs); - case ARM_ISAR_BKPT: - return ARM_ISAR(0, Debug_instrs); - case ARM_ISAR_CBZ: - return ARM_ISAR(0, CmpBranch_instrs); - case ARM_ISAR_BFC: - return ARM_ISAR(0, BitField_instrs); - case ARM_ISAR_CLZ: - return ARM_ISAR(0, BitCount_instrs); - case ARM_ISAR_SWP: - return ARM_ISAR(0, Swap_instrs); - case ARM_ISAR_BXJ: - return ARM_ISAR(1, Jazelle_instrs); - case ARM_ISAR_BX: - return ARM_ISAR(1, Interwork_instrs)>0; - case ARM_ISAR_BLX: - return ARM_ISAR(1, Interwork_instrs)>1; - case ARM_ISAR_MOVT: - return ARM_ISAR(1, Immediate_instrs); - case ARM_ISAR_IT: - return ARM_ISAR(1, IfThen_instrs); - case ARM_ISAR_SXTB: - return ARM_ISAR(1, Extend_instrs)>0; - case ARM_ISAR_SXTAB: - return ARM_ISAR(1, Extend_instrs)>1; - case ARM_ISAR_SXTB16: - return (ARM_ISAR(1, Extend_instrs)>1) && DSP_PRESENT(arm); - case ARM_ISAR_SRS: - return ARM_ISAR(1, Except_AR_instrs); - case ARM_ISAR_LDM_UR: - return ARM_ISAR(1, Except_instrs); - case ARM_ISAR_SETEND: - return ARM_ISAR(1, Endian_instrs); - case ARM_ISAR_REV: - return ARM_ISAR(2, Reversal_instrs)>0; - case ARM_ISAR_RBIT: - return ARM_ISAR(2, Reversal_instrs)>1; - case ARM_ISAR_MRS_AR: - return ARM_ISAR(2, PSR_AR_instrs); - case ARM_ISAR_UMULL: - return ARM_ISAR(2, MultU_instrs)>0; - case ARM_ISAR_UMAAL: - return ARM_ISAR(2, MultU_instrs)>1; - case ARM_ISAR_SMULL: - return ARM_ISAR(2, MultS_instrs)>0; - case ARM_ISAR_SMLABB: - return ARM_ISAR(2, MultS_instrs)>1; - case ARM_ISAR_SMLAD: - return ARM_ISAR(2, MultS_instrs)>2; - case ARM_ISAR_MLA: - return ARM_ISAR(2, Mult_instrs)>0; - case ARM_ISAR_MLS: - return ARM_ISAR(2, Mult_instrs)>1; - case ARM_ISAR_PLD: - return ARM_ISAR(2, MemHint_instrs)>0; - case ARM_ISAR_PLI: - return ARM_ISAR(2, MemHint_instrs)>2; - case ARM_ISAR_LDRD: - return ARM_ISAR(2, LoadStore_instrs); - case ARM_ISAR_NOP: - return ARM_ISAR(3, TrueNOP_instrs); - case ARM_ISAR_MOVLL: - return ARM_ISAR(3, ThumbCopy_instrs); - case ARM_ISAR_TBB: - return ARM_ISAR(3, TabBranch_instrs); - case ARM_ISAR_LDREX: - return ARM_ISAR(3, SynchPrim_instrs)>0; - case ARM_ISAR_CLREX: - return (ARM_ISAR(3, SynchPrim_instrs)>1) || (ARM_ISAR(4, SynchPrim_instrs_frac)==3); - case ARM_ISAR_LDREXD: - return ARM_ISAR(3, SynchPrim_instrs)>1; - case ARM_ISAR_SVC: - return ARM_ISAR(3, SVC_instrs); - case ARM_ISAR_SSAT: - return ARM_ISAR(3, SIMD_instrs)>0; - case ARM_ISAR_PKHBT: - return DSP_PRESENT(arm); - case ARM_ISAR_QADD: - return ARM_ISAR(3, Saturate_instrs); - case ARM_ISAR_MRS_M: - return ARM_ISAR(4, PSR_M_instrs); - case ARM_ISAR_DMB: - return ARM_ISAR(4, Barrier_instrs); - case ARM_ISAR_LDRBT: - return ARM_ISAR(4, Unpriv_instrs)>0; - case ARM_ISAR_LDRHT: - return ARM_ISAR(4, Unpriv_instrs)>1; - case ARM_ISAR_VMRS: - return FPU_PRESENT(arm); - case ARM_ISAR_VFPV2: - return supportVFP(state, state->info.dt1, 1); - case ARM_ISAR_VFPV3: - return supportVFP(state, state->info.dt1, 2); - case ARM_ISAR_VFPFMAC: - return FPU_PRESENT(arm) && SCS_FIELD(arm, MVFR1, VFP_FusedMAC); - case ARM_ISAR_VFPSQRT: - return SCS_FIELD(arm, MVFR0, SquareRoot) && supportVFP(state, state->info.dt1, 1); - case ARM_ISAR_VFPDIV: - return SCS_FIELD(arm, MVFR0, Divide) && supportVFP(state, state->info.dt1, 1); - case ARM_ISAR_VFPCVT2: - return supportVFP(state, state->info.dt1, 1) && supportVFP(state, state->info.dt2, 1); - case ARM_ISAR_VFPCVT3: - return supportVFP(state, state->info.dt1, 2) && supportVFP(state, state->info.dt2, 2); - case ARM_ISAR_VFPHP: - return FPU_PRESENT(arm) && SCS_FIELD(arm, MVFR1, VFP_HalfPrecision); - default: - VMI_ABORT("unimplemented case"); - return False; - } -} - -// -// Return a boolean indicating whether the processor supports the required -// architecture -// -static Bool supportedOnVariant(armP arm, armMorphStateP state) { - - armArchitecture configVariant = arm->configInfo.arch; - armArchitecture requiredVariant = state->info.support; - - if(ARM_INSTRUCTION_VERSION(requiredVariant) > getInstructionVersion(arm)) { - return False; - } else if(!ARM_SUPPORT(configVariant, requiredVariant & ~ARM_MASK_VERSION)) { - return False; - } else if(state->info.isar && SCS_USE_CPUID(arm)) { - return supportedByISAR(arm, state); - } else { - return True; - } -} - -// -// Create code for the ARM instruction at the simulated address referenced -// by 'thisPC'. -// -VMI_MORPH_FN(armMorphInstruction) { - - armP arm = (armP)processor; - armMorphState state; - - // seed morph-time ITSTATE if this is the first instruction in a code block - if(firstInBlock) { - arm->itStateMT = arm->itStateRT; - } - - // get instruction and instruction type - armDecode(arm, thisPC, &state.info); - - // get morpher attributes for the decoded instruction and initialize other - // state fields - state.attrs = &armMorphTable[state.info.type]; - state.arm = arm; - state.nextPC = state.info.thisPC + state.info.bytes; - state.skipLabel = 0; - state.tempIdx = 0; - state.pcFetched = False; - state.pcSet = ASPC_NA; - state.pcImmediate = 0; - state.setMode = False; - - // if this is the first instruction in the block, mark all derived flags as - // invalid - if(firstInBlock) { - resetDerivedFlags(&state); - } - - if(disableMorph(&state)) { - // no action if in disassembly mode - } else if(!supportedOnVariant(arm, &state)) { - // instruction not supported on this variant - emitNotVariant(&state); - } else if(state.attrs->morphCB) { - // translate the instruction - emitImplemented(&state); - } else if(state.info.type==ARM_IT_LAST) { - // take UsageFault exception - emitUsageFault(&state, EXC_UNDEF_UNDEFINSTR); - } else { - // here if no morph callback specified - emitUnimplemented(&state); - } -} - -// -// Snap instruction fetch addresses to the appropriate boundary -// -VMI_FETCH_SNAP_FN(armFetchSnap) { - - armP arm = (armP)processor; - Uns32 snap = IN_THUMB_MODE(arm) ? 1 : 3; - - return thisPC & ~snap; -} - - diff --git a/simulators/ovp/armmModel/armmMorphTable.c b/simulators/ovp/armmModel/armmMorphTable.c deleted file mode 100644 index c2ff646c..00000000 --- a/simulators/ovp/armmModel/armmMorphTable.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiMessage.h" - -// model header files -#include "armEmit.h" -#include "armMorph.h" -#include "armMorphEntries.h" -#include "armMorphFunctions.h" -#include "armRegisters.h" -#include "armStructure.h" -#include "armUtils.h" - - -//////////////////////////////////////////////////////////////////////////////// -// FLAGS -//////////////////////////////////////////////////////////////////////////////// - -const static vmiFlags flagsZNCV = { - ARM_CF_CONST, - { - [vmi_CF] = ARM_CF_CONST, - [vmi_PF] = VMI_NOFLAG_CONST, - [vmi_ZF] = ARM_ZF_CONST, - [vmi_SF] = ARM_NF_CONST, - [vmi_OF] = ARM_VF_CONST - } -}; - -const static vmiFlags flagsZNBV = { - ARM_CF_CONST, - { - [vmi_CF] = ARM_CF_CONST, - [vmi_PF] = VMI_NOFLAG_CONST, - [vmi_ZF] = ARM_ZF_CONST, - [vmi_SF] = ARM_NF_CONST, - [vmi_OF] = ARM_VF_CONST - }, - vmi_FN_CF_IN|vmi_FN_CF_OUT -}; - -const static vmiFlags flagsZN = { - ARM_CF_CONST, - { - [vmi_CF] = VMI_NOFLAG_CONST, - [vmi_PF] = VMI_NOFLAG_CONST, - [vmi_ZF] = ARM_ZF_CONST, - [vmi_SF] = ARM_NF_CONST, - [vmi_OF] = VMI_NOFLAG_CONST - } -}; - -const static vmiFlags flagsCIn = { - ARM_CF_CONST, - { - [vmi_CF] = VMI_NOFLAG_CONST, - [vmi_PF] = VMI_NOFLAG_CONST, - [vmi_ZF] = VMI_NOFLAG_CONST, - [vmi_SF] = VMI_NOFLAG_CONST, - [vmi_OF] = VMI_NOFLAG_CONST - } -}; - -const static vmiFlags flagsBIn = { - ARM_CF_CONST, - { - [vmi_CF] = VMI_NOFLAG_CONST, - [vmi_PF] = VMI_NOFLAG_CONST, - [vmi_ZF] = VMI_NOFLAG_CONST, - [vmi_SF] = VMI_NOFLAG_CONST, - [vmi_OF] = VMI_NOFLAG_CONST - }, - vmi_FN_CF_IN -}; - -// Macro accessors for flags -#define FLAGS_ZNCV &flagsZNCV -#define FLAGS_ZNBV &flagsZNBV -#define FLAGS_ZN &flagsZN -#define FLAGS_CIN &flagsCIn -#define FLAGS_BIN &flagsBIn - - -//////////////////////////////////////////////////////////////////////////////// -// MORPHER DISPATCH TABLE -//////////////////////////////////////////////////////////////////////////////// - -const armMorphAttr armMorphTable[ARM_IT_LAST+1] = { - - //////////////////////////////////////////////////////////////////////////// - // ARM INSTRUCTIONS - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - MORPH_SET_ADC (ADC, vmi_ADC, FLAGS_ZNCV, FLAGS_CIN, False), - MORPH_SET_ADC (ADD, vmi_ADD, FLAGS_ZNCV, FLAGS_CIN, False), - MORPH_SET_ADC (AND, vmi_AND, FLAGS_ZN, 0, True ), - MORPH_SET_ADC (BIC, vmi_ANDN, FLAGS_ZN, 0, True ), - MORPH_SET_ADC (EOR, vmi_XOR, FLAGS_ZN, 0, True ), - MORPH_SET_MOV (MOV, vmi_MOV, FLAGS_ZN, 0, True ), - MORPH_SET_ADC (MUL, vmi_MUL, FLAGS_ZN, 0, True ), - MORPH_SET_MOV (MVN, vmi_NOT, FLAGS_ZN, 0, True ), - MORPH_SET_MOV (NEG, vmi_NEG, FLAGS_ZNBV, 0, False), - MORPH_SET_ADC (ORN, vmi_ORN, FLAGS_ZN, 0, True ), - MORPH_SET_ADC (ORR, vmi_OR, FLAGS_ZN, 0, True ), - MORPH_SET_ADC (RSB, vmi_RSUB, FLAGS_ZNBV, FLAGS_BIN, False), - MORPH_SET_ADC (RSC, vmi_RSBB, FLAGS_ZNBV, FLAGS_BIN, False), - MORPH_SET_ADC (SBC, vmi_SBB, FLAGS_ZNBV, FLAGS_BIN, False), - MORPH_SET_ADC (SUB, vmi_SUB, FLAGS_ZNBV, FLAGS_BIN, False), - - // ARMv6T2 move instructions - MORPH_SINGLE (MOVT), - MORPH_SINGLE (MOVW), - - // multiply instructions - MORPH_SET_MLA (MLA, FLAGS_ZN), - MORPH_SET_MLA (MLS, FLAGS_ZN), - MORPH_SET_MLA (MUL, FLAGS_ZN), - MORPH_SET_SMULL (SMLAL, MLAL, vmi_IMUL, FLAGS_ZN), - MORPH_SET_SMULL (SMULL, MULL, vmi_IMUL, FLAGS_ZN), - MORPH_SET_SMULL (UMAAL, MAAL, vmi_MUL, FLAGS_ZN), - MORPH_SET_SMULL (UMLAL, MLAL, vmi_MUL, FLAGS_ZN), - MORPH_SET_SMULL (UMULL, MULL, vmi_MUL, FLAGS_ZN), - - // compare instructions - MORPH_SET_CMN (CMN, vmi_ADD, FLAGS_ZNCV, FLAGS_CIN, False), - MORPH_SET_CMN (CMP, vmi_SUB, FLAGS_ZNBV, FLAGS_BIN, False), - MORPH_SET_CMN (TEQ, vmi_XOR, FLAGS_ZN, 0, True ), - MORPH_SET_CMN (TST, vmi_AND, FLAGS_ZN, 0, True ), - - // branch instructions - MORPH_SET_B (B, False), - MORPH_SET_B (BL, True ), - MORPH_SET_BLX2 (BLX2, True ), - MORPH_SET_BLX2 (BX, False), - - // miscellaneous instructions - MORPH_SINGLE (BKPT), - MORPH_SINGLE (CLZ ), - MORPH_SINGLE (SWI ), - - // load and store instructions - MORPH_SET_LDR (LDR, LDR ), - MORPH_SET_LDR (LDRB, LDR ), - MORPH_SET_LDR (LDRBT, LDR ), - MORPH_SET_LDRH (LDRH, LDR ), - MORPH_SET_LDRH (LDRSB, LDR ), - MORPH_SET_LDRH (LDRSH, LDR ), - MORPH_SET_LDR (LDRT, LDR ), - MORPH_SET_LDR (STR, STR ), - MORPH_SET_LDR (STRB, STR ), - MORPH_SET_LDR (STRBT, STR ), - MORPH_SET_LDRH (STRH, STR ), - MORPH_SET_LDR (STRT, STR ), - - // load and store multiple instructions - MORPH_SET_LDM1 (LDM1), - MORPH_SINGLE (STM1), - - // ARMv6T2 load and store instructions - MORPH_SET_LDRH (LDRHT, LDR), - MORPH_SET_LDRH (LDRSBT, LDR), - MORPH_SET_LDRH (LDRSHT, LDR), - MORPH_SET_LDRH (STRHT, STR), - - // synchronization primitives - MORPH_SET_SWP (LDREX, LDREX), - MORPH_SET_SWP (LDREXB, LDREX), - MORPH_SET_SWP (LDREXH, LDREX), - MORPH_SET_SWP (STREX, STREX), - MORPH_SET_SWP (STREXB, STREX), - MORPH_SET_SWP (STREXH, STREX), - - // coprocessor instructions (all UsageFault) - MORPH_SET_SWP (CDP, UsageFaultCP), - MORPH_SET_SWP (CDP2, UsageFaultCP), - MORPH_SET_LDC (LDC, UsageFaultCP), - MORPH_SET_LDC (LDC2, UsageFaultCP), - MORPH_SET_SWP (MCR, UsageFaultCP), - MORPH_SET_SWP (MCR2, UsageFaultCP), - MORPH_SET_SWP (MRC, UsageFaultCP), - MORPH_SET_SWP (MRC2, UsageFaultCP), - MORPH_SET_LDC (STC, UsageFaultCP), - MORPH_SET_LDC (STC2, UsageFaultCP), - - // status register access instructions - MORPH_SINGLE (MRS), - MORPH_SINGLE (MSR), - - // hint instructions - MORPH_SET_NOP (NOP ), - MORPH_SET_NOP (YIELD), - MORPH_SINGLE (WFE ), - MORPH_SINGLE (WFI ), - MORPH_SINGLE (SEV ), - MORPH_SET_NOP (DBG ), - - // ARMv6 miscellaneous instructions - MORPH_SINGLE (CPS ), - MORPH_SINGLE (CLREX ), - MORPH_SET_NOP (DSB ), - MORPH_SET_NOP (ISB ), - - // ARMv7 miscellaneous instructions - MORPH_SET_PLD (PLD), - MORPH_SET_PLD (PLI), - MORPH_SET_NOP (DMB), - - //////////////////////////////////////////////////////////////////////////// - // DSP INSTRUCTIONS - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - MORPH_SINGLE (QADD ), - MORPH_SINGLE (QDADD), - MORPH_SINGLE (QDSUB), - MORPH_SINGLE (QSUB ), - - // multiply instructions - MORPH_SET_SMLA_XY (SMLA ), - MORPH_SET_SMLA_XY (SMLAL), - MORPH_SET_SMLAW_Y (SMLAW), - MORPH_SET_SMLA_XY (SMUL ), - MORPH_SET_SMLAW_Y (SMULW), - - // load and store instructions - MORPH_SET_LDRH (LDRD, LDR), - MORPH_SET_LDRH (STRD, STR), - - // coprocessor instructions (all UsageFault) - MORPH_SET_SWP (MCRR, UsageFaultCP), - MORPH_SET_SWP (MCRR2, UsageFaultCP), - MORPH_SET_SWP (MRRC, UsageFaultCP), - MORPH_SET_SWP (MRRC2, UsageFaultCP), - - //////////////////////////////////////////////////////////////////////////// - // MEDIA INSTRUCTIONS - //////////////////////////////////////////////////////////////////////////// - - // basic instructions - MORPH_SINGLE (USAD8 ), - MORPH_SINGLE (USADA8), - MORPH_SINGLE (SBFX ), - MORPH_SINGLE (BFC ), - MORPH_SINGLE (BFI ), - MORPH_SINGLE (UBFX ), - - // parallel add/subtract instructions - MORPH_SET_PAS (S, vmi_ADD, vmi_SUB, True, True, False), - MORPH_SET_PAS (Q, vmi_ADDSQ, vmi_SUBSQ, False, False, False), - MORPH_SET_PAS (SH, vmi_ADD, vmi_SUB, True, False, True ), - MORPH_SET_PAS (U, vmi_ADD, vmi_SUB, False, True, False), - MORPH_SET_PAS (UQ, vmi_ADDUQ, vmi_SUBUQ, False, False, False), - MORPH_SET_PAS (UH, vmi_ADD, vmi_SUB, False, False, True ), - - // packing, unpacking, saturation and reversal instructions - MORPH_SINGLE (PKHBT ), - MORPH_SINGLE (PKHTB ), - MORPH_SINGLE (SSAT ), - MORPH_SINGLE (SSAT16 ), - MORPH_SINGLE (USAT ), - MORPH_SINGLE (USAT16 ), - MORPH_SINGLE (SXTAB ), - MORPH_SINGLE (UXTAB ), - MORPH_SINGLE (SXTAB16), - MORPH_SINGLE (UXTAB16), - MORPH_SINGLE (SXTAH ), - MORPH_SINGLE (UXTAH ), - MORPH_SINGLE (SXTB ), - MORPH_SINGLE (UXTB ), - MORPH_SINGLE (SXTB16 ), - MORPH_SINGLE (UXTB16 ), - MORPH_SINGLE (SXTH ), - MORPH_SINGLE (UXTH ), - MORPH_SINGLE (SEL ), - MORPH_SINGLE (REV ), - MORPH_SINGLE (REV16 ), - MORPH_SINGLE (RBIT ), - MORPH_SINGLE (REVSH ), - - // signed multiply instructions - MORPH_SET_MEDIA_X (SMLAD, SMLXD, vmi_ADD), - MORPH_SET_MEDIA_X (SMUAD, SMUXD, vmi_ADD), - MORPH_SET_MEDIA_X (SMLSD, SMLXD, vmi_SUB), - MORPH_SET_MEDIA_X (SMUSD, SMUXD, vmi_SUB), - MORPH_SET_MEDIA_X (SMLALD, SMLXLD, vmi_ADD), - MORPH_SET_MEDIA_X (SMLSLD, SMLXLD, vmi_SUB), - MORPH_SET_MEDIA_R (SMMLA, SMMLX, vmi_ADD, True ), - MORPH_SET_MEDIA_R (SMMUL, SMMLX, vmi_ADD, False), - MORPH_SET_MEDIA_R (SMMLS, SMMLX, vmi_RSUB, True ), - - // VFP data processing instructions - MORPH_SET_VFP_RRR_F (VMLA_VFP, VMulAcc_VFP, vmi_FADD, 0), - MORPH_SET_VFP_RRR_F (VMLS_VFP, VMulAcc_VFP, vmi_FSUB, 0), - MORPH_SET_VFP_RRR_F (VNMLA_VFP, VMulAcc_VFP, vmi_FSUB, 1), - MORPH_SET_VFP_RRR_F (VNMLS_VFP, VMulAcc_VFP, vmi_FADD, 1), - MORPH_SET_VFP_RRR_F (VNMUL_VFP, VFPBinop, vmi_FMUL, 1), - MORPH_SET_VFP_RRR_F (VMUL_VFP, VFPBinop, vmi_FMUL, 0), - MORPH_SET_VFP_RRR_F (VADD_VFP, VFPBinop, vmi_FADD, 0), - MORPH_SET_VFP_RRR_F (VSUB_VFP, VFPBinop, vmi_FSUB, 0), - MORPH_SET_VFP_RRR_F (VDIV_VFP, VFPBinop, vmi_FDIV, 0), - MORPH_SET_VFP_FMAC_F (VFNMA_VFP, 1, 1), - MORPH_SET_VFP_FMAC_F (VFNMS_VFP, 0, 1), - MORPH_SET_VFP_FMAC_F (VFMA_VFP, 0, 0), - MORPH_SET_VFP_FMAC_F (VFMS_VFP, 1, 0), - MORPH_SET_VFP_S (VMOVI_VFP, VMOVI_VFP), - MORPH_SET_VFP_S (VMOVR_VFP, VMOVR_VFP), - MORPH_SET_VFP_S (VABS_VFP, VABS_VFP), - MORPH_SET_VFP_S (VNEG_VFP, VNEG_VFP), - MORPH_SET_VFP_RR_F (VSQRT_VFP, vmi_FSQRT), - MORPH_SET_VFP_VCMP (VCMP_VFP, VCMP_VFP, 1), - MORPH_SET_VFP_VCMP (VCMPE_VFP, VCMP_VFP, 0), - MORPH_SET_VFP_VCMP (VCMP0_VFP, VCMP0_VFP, 1), - MORPH_SET_VFP_VCMP (VCMPE0_VFP, VCMP0_VFP, 0), - // VCVT between half precision and single precision - MORPH_SET_VFP_VCVT_H (VCVTTFH_VFP, VCVT_SH_VFP, 2, 1), - MORPH_SET_VFP_VCVT_H (VCVTBFH_VFP, VCVT_SH_VFP, 2, 0), - MORPH_SET_VFP_VCVT_H (VCVTTHF_VFP, VCVT_HS_VFP, 2, 1), - MORPH_SET_VFP_VCVT_H (VCVTBHF_VFP, VCVT_HS_VFP, 2, 0), - // VCVT from single precision to Integer (signed or unsigned) with round option - MORPH_SET_VFP_VCVT (VCVTRUF_VFP, VCVT_IF_VFP, 4, 0, 1), - MORPH_SET_VFP_VCVT (VCVTUF_VFP, VCVT_IF_VFP, 4, 0, 0), - MORPH_SET_VFP_VCVT (VCVTRSF_VFP, VCVT_IF_VFP, 4, 1, 1), - MORPH_SET_VFP_VCVT (VCVTSF_VFP, VCVT_IF_VFP, 4, 1, 0), - // VCVT from single precision to Fixed (signed or unsigned, word or half) - MORPH_SET_VFP_VCVT (VCVTXFUW_VFP, VCVT_XF_VFP, 4, 0, 0), - MORPH_SET_VFP_VCVT (VCVTXFSW_VFP, VCVT_XF_VFP, 4, 1, 0), - MORPH_SET_VFP_VCVT (VCVTXFUH_VFP, VCVT_XF_VFP, 2, 0, 0), - MORPH_SET_VFP_VCVT (VCVTXFSH_VFP, VCVT_XF_VFP, 2, 1, 0), - // VCVT from Fixed (signed or unsigned, word or half) to single precision - MORPH_SET_VFP_VCVT (VCVTFXUW_VFP, VCVT_FX_VFP, 4, 0, 0), - MORPH_SET_VFP_VCVT (VCVTFXSW_VFP, VCVT_FX_VFP, 4, 1, 0), - MORPH_SET_VFP_VCVT (VCVTFXUH_VFP, VCVT_FX_VFP, 2, 0, 0), - MORPH_SET_VFP_VCVT (VCVTFXSH_VFP, VCVT_FX_VFP, 2, 1, 0), - // VCVT From Integer (signed or unsigned) to single precision - MORPH_SET_VFP_VCVT (VCVTFU_VFP, VCVT_FI_VFP, 4, 0, 1), - MORPH_SET_VFP_VCVT (VCVTFS_VFP, VCVT_FI_VFP, 4, 1, 1), - - // 8, 16 and 32-bit transfer instructions - MORPH_SET_SINGLE_VFP (VMRS), - MORPH_SET_SINGLE_VFP (VMSR), - MORPH_SET_SINGLE_VFP (VMOVRS), - MORPH_SET_SINGLE_VFP (VMOVSR), - MORPH_SET_SINGLE_VFP (VMOVRZ), - MORPH_SET_SINGLE_VFP (VMOVZR), - - // Extension register load/store instructions - MORPH_SET_VFP_DS (VLDR, VLDR), - MORPH_SET_VFP_DS (VSTR, VSTR), - MORPH_SET_VFP_DS (VLDR, VLDR), - MORPH_SET_VFP_DS (VSTR, VSTR), - MORPH_SET_VFP_DS (VLDMIA, VLDM), - MORPH_SET_VFP_DS (VLDMIAW, VLDM), - MORPH_SET_VFP_DS (VLDMDBW, VLDM), - MORPH_SET_VFP_DS (VPOP, VLDM), - MORPH_SET_VFP_DS (VSTMIA, VSTM), - MORPH_SET_VFP_DS (VSTMIAW, VSTM), - MORPH_SET_VFP_DS (VSTMDBW, VSTM), - MORPH_SET_VFP_DS (VPUSH, VSTM), - - // 64-bit transfer instructions - MORPH_SET_SINGLE_VFP (VMOVRRD), - MORPH_SET_SINGLE_VFP (VMOVDRR), - MORPH_SET_SINGLE_VFP (VMOVRRSS), - MORPH_SET_SINGLE_VFP (VMOVSSRR), - - //////////////////////////////////////////////////////////////////////////// - // THUMB INSTRUCTIONS (WHEN DISTINCT FROM ARM INSTRUCTIONS) - //////////////////////////////////////////////////////////////////////////// - - // data processing instructions - MORPH_SET_ADD4 (ADD4, vmi_ADD, 0, 0, False), - MORPH_SET_ADD6 (ADD6, vmi_ADD, 0, 0, False), - MORPH_SET_ADD7 (ADD7, vmi_ADD, 0, 0, False), - MORPH_SET_ADD7 (SUB4, vmi_SUB, 0, 0, False), - MORPH_SET_MOV3 (MOV3, vmi_MOV, 0, 0, False), - - // address instructions - MORPH_SET_ADR (ADD_ADR, False), - MORPH_SET_ADR (SUB_ADR, True ), - - // branch instructions - MORPH_SET_CBZ (CBNZ, False), - MORPH_SET_CBZ (CBZ, True ), - MORPH_SINGLE (TB), - - // divide instructions - MORPH_SET_SDIV (SDIV, vmi_IDIV), - MORPH_SET_SDIV (UDIV, vmi_DIV ), -}; diff --git a/simulators/ovp/armmModel/armmParameters.c b/simulators/ovp/armmModel/armmParameters.c deleted file mode 100644 index eb457a37..00000000 --- a/simulators/ovp/armmModel/armmParameters.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// Imperas header files -#include "hostapi/impAlloc.h" - -// VMI header files -#include "vmi/vmiAttrs.h" -#include "vmi/vmiParameters.h" -#include "vmi/vmiMessage.h" - -#include "armFunctions.h" -#include "armConfig.h" -#include "armmParameters.h" -#include "armStructure.h" -#include "armVariant.h" - -static vmiEnumParameter compatTable[] = { - {"ISA", COMPAT_ISA}, - {"gdb", COMPAT_GDB}, - {"nopBKPT", COMPAT_CODE_SOURCERY}, - { 0, 0 } -}; - -// -// Table of parameter specs -// -static vmiParameter formals[] = { - - VMI_ENUM_PARAM_SPEC( armParamValues, variant, NULL, "Select variant (either a generic ISA or a specific model)"), // filled in by getVariantList() - VMI_ENDIAN_PARAM_SPEC(armParamValues, endian, "Model endian"), - VMI_ENUM_PARAM_SPEC( armParamValues, compatibility, compatTable, "Specify compatibility mode (default: ISA)"), - - VMI_BOOL_PARAM_SPEC( armParamValues, verbose, 1, "Specify verbosity of output" ), - VMI_BOOL_PARAM_SPEC( armParamValues, showHiddenRegs, 0, "Show hidden registers during register tracing" ), - VMI_BOOL_PARAM_SPEC( armParamValues, UAL, 1, "Disassemble using UAL syntax" ), - VMI_BOOL_PARAM_SPEC( armParamValues, enableVFPAtReset, 0, "Enable vector floating point (VFP) instructions at reset. (Enables cp10/11 in CPACR)" ), - VMI_BOOL_PARAM_SPEC( armParamValues, disableBitBand, 0, "Disable bit banding"), - VMI_BOOL_PARAM_SPEC( armParamValues, resetAtTime0, 1, "Reset the model at time=0 (NB: default=1)" ), - - VMI_UNS32_PARAM_SPEC( armParamValues, override_CPUID , 0, 0, VMI_MAXU32, "Override system CPUID register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_MPU_TYPE , 0, 0, VMI_MAXU32, "Override system MPU_TYPE register"), - - VMI_ENDIAN_PARAM_SPEC(armParamValues, instructionEndian, "The ARMv7-M is defined to always fetch instructions in little endian order; this attribute allows the profile-defined instruction endianness to be overridden if required"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_debugMask , 0, 0, VMI_MAXU32, "Specifies debug mask, enabling debug output for model components"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_MPUType , 0, 0, VMI_MAXU32, "Override MPUType register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_InstructionAttributes0, 0, 0, VMI_MAXU32, "Override InstructionAttributes0 register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_InstructionAttributes1, 0, 0, VMI_MAXU32, "Override InstructionAttributes1 register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_InstructionAttributes2, 0, 0, VMI_MAXU32, "Override InstructionAttributes2 register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_InstructionAttributes3, 0, 0, VMI_MAXU32, "Override InstructionAttributes3 register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_InstructionAttributes4, 0, 0, VMI_MAXU32, "Override InstructionAttributes4 register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_InstructionAttributes5, 0, 0, VMI_MAXU32, "Override InstructionAttributes5 register"), - - VMI_UNS32_PARAM_SPEC( armParamValues, override_MVFR0, 0, 0, VMI_MAXU32, "Override MVFR0 register"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_MVFR1, 0, 0, VMI_MAXU32, "Override MVFR1 register"), - - VMI_UNS32_PARAM_SPEC( armParamValues, override_rotateUnaligned , 0, 0, 1, "Specifies that data from unaligned loads by LDR, LDRT or SWP should be rotated (if 1)"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_align64as32 , 0, 0, 1, "Specifies that 64:bit loads and stores are aligned to 32:bit boundaries (if 1)"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_STRoffsetPC12 , 0, 0, 1, "Specifies that STR/STR of PC should do so with 12:byte offset from the current instruction (if 1), otherwise an 8:byte offset is used"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_ERG , 0, 0, 1024, "Specifies exclusive reservation granule"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_priorityBits , 0, 0, 8 , "Specifies number of priority bits in BASEPRI etc (1-8, default is 3)"), - VMI_UNS32_PARAM_SPEC( armParamValues, override_numInterrupts , 0, 0, 4096, "Specifies number of external interrupt lines (0-495, default is 16)"), - -VMI_UNS32_PARAM_SPEC( armParamValues, fail_salp , 0, 0, VMI_MAXU32, "Address of Fail* SAL Object"), - - VMI_END_PARAM -}; - -static Uns32 countVariants(void) { - armConfigCP cfg = armConfigTable; - Uns32 i = 0; - while(cfg->name) { - cfg++; - i++; - } - return i; -} - -// -// First time through, malloc and fill the variant list from the config table -// -static vmiEnumParameterP getVariantList() { - static vmiEnumParameterP list = NULL; - if (!list) { - Uns32 v = 1+ countVariants(); - list = STYPE_CALLOC_N(vmiEnumParameter, v); - vmiEnumParameterP prm; - armConfigCP cfg; - Uns32 i; - for (i = 0, cfg = armConfigTable, prm = list; - cfg->name; - i++, cfg++, prm++) { - prm->name = cfg->name; - prm->value = i; - } - } - return list; -} - -// -// First time through, fill the formals table -// -static vmiParameterP getFormals(void) { - static Bool first = True; - if(first) { - first = False; - formals[0].u.enumParam.legalValues = getVariantList(); - } - return formals; -} - - -// -// Function to iterate the parameter specs -// -VMI_PROC_PARAM_SPECS_FN(armGetParamSpec) { - if(!prev) { - return getFormals(); - } else { - prev++; - if (prev->name) - return prev; - else - return 0; - } -} - -// -// Get the size of the parameter values table -// -VMI_PROC_PARAM_TABLE_SIZE_FN(armParamValueSize) { - return sizeof(armParamValues); -} - - diff --git a/simulators/ovp/armmModel/armmParameters.h b/simulators/ovp/armmModel/armmParameters.h deleted file mode 100644 index 3bcf8849..00000000 --- a/simulators/ovp/armmModel/armmParameters.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ARMM_PARAMETERS_H -#define ARMM_PARAMETERS_H - -// VMI header files -#include "vmi/vmiAttrs.h" -#include "vmi/vmiParameters.h" - -#include "armTypeRefs.h" - -// -// Define the attributes value structure -// -typedef struct armParamValuesS { - VMI_ENUM_PARAM(variant); - VMI_ENDIAN_PARAM(endian); - VMI_ENUM_PARAM(compatibility); - - VMI_BOOL_PARAM(verbose); - VMI_BOOL_PARAM(showHiddenRegs); - VMI_BOOL_PARAM(UAL); - VMI_BOOL_PARAM(enableVFPAtReset); - VMI_BOOL_PARAM(disableBitBand); - VMI_BOOL_PARAM(resetAtTime0); - - VMI_UNS32_PARAM(override_CPUID); - VMI_UNS32_PARAM(override_MPU_TYPE); - - VMI_ENUM_PARAM(instructionEndian); - VMI_UNS32_PARAM(override_debugMask); - VMI_UNS32_PARAM(override_MPUType); - VMI_UNS32_PARAM(override_InstructionAttributes0); - VMI_UNS32_PARAM(override_InstructionAttributes1); - VMI_UNS32_PARAM(override_InstructionAttributes2); - VMI_UNS32_PARAM(override_InstructionAttributes3); - VMI_UNS32_PARAM(override_InstructionAttributes4); - VMI_UNS32_PARAM(override_InstructionAttributes5); - - VMI_UNS32_PARAM(override_MVFR0); - VMI_UNS32_PARAM(override_MVFR1); - - VMI_UNS32_PARAM(override_rotateUnaligned); - VMI_UNS32_PARAM(override_align64as32); - VMI_UNS32_PARAM(override_STRoffsetPC12); - VMI_UNS32_PARAM(override_ERG); - VMI_UNS32_PARAM(override_priorityBits); - VMI_UNS32_PARAM(override_numInterrupts); - - VMI_UNS32_PARAM(fail_salp); - - - -} armParamValues, *armParamValuesP; - -#endif diff --git a/simulators/ovp/armmModel/armmSemiHost.c b/simulators/ovp/armmModel/armmSemiHost.c deleted file mode 100644 index efae648d..00000000 --- a/simulators/ovp/armmModel/armmSemiHost.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiTypes.h" -#include "vmi/vmiMessage.h" -#include "vmi/vmiMt.h" - -// model header files -#include "armFunctions.h" -#include "armRegisters.h" -#include "armStructure.h" - - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_SEMIHOST" - -// -// Return processor endianness -// -inline static memEndian getEndian(armP arm) { - return armGetEndian((vmiProcessorP)arm, False); -} - -// -// Morph return from an opaque intercepted function -// -VMI_INT_RETURN_FN(armIntReturnCB) { - vmimtUncondJumpReg(0, ARM_REG(ARM_REG_LR), VMI_NOREG, vmi_JH_RETURN); -} - -// -// This callback should create code to assign function result to the standard -// return result register -// -VMI_INT_RESULT_FN(armIntResultCB) { - vmimtMoveRR(32, ARM_REG(0), VMI_FUNCRESULT); -} - -// -// This callback should create code to push 32-bit function parameter 'paramNum' -// -static Uns32 push4ByteArg(vmiProcessorP processor, Uns32 paramNum) { - - if(paramNum<=3) { - - // argument in a register - vmimtArgReg(32, ARM_REG(paramNum)); - - } else { - - // argument on the stack - armP arm = (armP)processor; - - // fetch into a temporary - vmimtLoadRRO( - 32, // destBits - 32, // memBits - (paramNum-4)*4, // offset - ARM_TEMP(0), // destination (rd) - ARM_REG(ARM_REG_SP), // stack address (ra) - getEndian(arm), // endian - False, // signExtend - False // checkAlign - ); - - // push temporary argument - vmimtArgReg(32, ARM_TEMP(0)); - } - - return paramNum+1; -} - -// -// This callback should create code to push 64-bit function parameter 'paramNum' -// -static Uns32 push8ByteArg(vmiProcessorP processor, Uns32 paramNum) { - - paramNum += push4ByteArg(processor, paramNum); - paramNum += push4ByteArg(processor, paramNum); - - return paramNum; -} - -// -// This callback should create code to push address function parameter 'paramNum' -// -static Uns32 pushAddressArg(vmiProcessorP processor, Uns32 paramNum) { - - if(paramNum<=3) { - - // argument in a register - vmimtArgRegSimAddress(32, ARM_REG(paramNum)); - - } else { - - // argument on the stack - armP arm = (armP)processor; - - // fetch into a temporary - vmimtLoadRRO( - 32, // destBits - 32, // memBits - (paramNum-4)*4, // offset - ARM_TEMP(0), // destination (rd) - ARM_REG(ARM_REG_SP), // stack address (ra) - getEndian(arm), // endian - False, // signExtend - False // checkAlign - ); - - // push temporary argument - vmimtArgRegSimAddress(32, ARM_TEMP(0)); - } - - return paramNum+1; -} - -// -// This callback should create code to push function arguments prior to an -// Imperas standard intercept -// -VMI_INT_PAR_FN(armIntParCB) { - - Uns32 paramNum = 0; - char ch; - - while((ch=*format++)) { - - switch(ch) { - - case '4': - paramNum = push4ByteArg(processor, paramNum); - break; - - case '8': - paramNum = push8ByteArg(processor, paramNum); - break; - - case 'a': - paramNum = pushAddressArg(processor, paramNum); - break; - - default: - VMI_ABORT("Unrecognised format character '%c'", ch); - } - } -} - diff --git a/simulators/ovp/armmModel/armmSys.c b/simulators/ovp/armmModel/armmSys.c deleted file mode 100644 index 7a5f1068..00000000 --- a/simulators/ovp/armmModel/armmSys.c +++ /dev/null @@ -1,1683 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// standard header files -#include -#include -#include - -// VMI header files -#include "vmi/vmiMessage.h" -#include "vmi/vmiRt.h" -#include "vmi/vmiView.h" - -// model header files -#include "armExceptions.h" -#include "armExceptionTypes.h" -#include "armMessage.h" -#include "armStructure.h" -#include "armSys.h" -#include "armSysRegisters.h" -#include "armUtils.h" -#include "armVM.h" - - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_SCS" - - -//////////////////////////////////////////////////////////////////////////////// -// UTILITIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Return current program counter -// -inline static Uns32 getPC(armP arm) { - return vmirtGetPC((vmiProcessorP)arm); -} - -// -// Is the numbered exception enabled? -// -inline static Bool isEnabled(armP arm, armExceptNum num) { - return EX_MASK_GET(arm->xEnable, num); -} - -// -// Is the numbered exception pending? -// -inline static Bool isPending(armP arm, armExceptNum num) { - return EX_MASK_GET(arm->xPend, num); -} - -// -// Is the numbered exception active? -// -inline static Bool isActive(armP arm, armExceptNum num) { - return EX_MASK_GET(arm->xActive, num); -} - -// -// Enable or disabled the numbered exception -// -inline static void setEnabled(armP arm, armExceptNum num, Bool set) { - EX_MASK_SET_V(arm->xEnable, num, set); -} - -// -// Set or clear the pending bit for the passed exception -// -inline static void setPending(armP arm, armExceptNum num, Bool set) { - EX_MASK_SET_V(arm->xPend, num, set); -} - -// -// Set or clear the active bit for the passed exception -// -inline static void setActive(armP arm, armExceptNum num, Bool set) { - EX_MASK_SET_V(arm->xActive, num, set); -} - -// -// Write a value to the passed net -// -inline static void writeNet(armP arm, Uns32 netHandle, Uns32 value) { - if(netHandle) { - vmirtWriteNetPort((vmiProcessorP)arm, netHandle, value); - } -} - -// -// Is the region number valid? -// -inline static Bool validRegion(armP arm, Uns32 region) { - return (region < SCS_FIELD(arm, MPU_TYPE, DREGION)); -} - -//////////////////////////////////////////////////////////////////////////////// -// READ AND WRITE CALLBACKS -//////////////////////////////////////////////////////////////////////////////// - -// -// System register read callback type -// -#define ARM_SCS_READFN(_NAME) Uns32 _NAME( \ - armP arm, \ - armSCSRegId id, \ - Uns32 byteOffset \ -) -typedef ARM_SCS_READFN((*armSCSReadFn)); - -// -// System register write callback type -// -#define ARM_SCS_WRITEFN(_NAME) void _NAME( \ - armP arm, \ - armSCSRegId id, \ - Uns32 newValue, \ - Uns32 byteOffset \ -) -typedef ARM_SCS_WRITEFN((*armSCSWriteFn)); - -// -// Update a system register, preserving read-only bits -// -#define UPDATE_SCS_MASKED(_P, _R, _NEW) \ - SCS_REG_UNS32(_P, _R) = ( \ - (SCS_REG_UNS32(_P, _R) & ~SCS_WRITE_MASK_##_R) | \ - (_NEW & SCS_WRITE_MASK_##_R) \ - ) - -// -// Dummy function to ignore a system register read -// -static ARM_SCS_READFN(ignoreSysRead) { - - Uns32 thisPC = getPC(arm); - - vmiMessage("W", CPU_PREFIX"_ISR", - SRCREF_FMT "SCS register read ignored (return 0)", - SRCREF_ARGS(arm, thisPC) - ); - - return 0; -} - -// -// Dummy function to ignore a system register write -// -static ARM_SCS_WRITEFN(ignoreSysWrite) { - - Uns32 thisPC = getPC(arm); - - vmiMessage("W", CPU_PREFIX"_ISW", - SRCREF_FMT "SCS register write ignored", - SRCREF_ARGS(arm, thisPC) - ); -} - -// -// Write MPU_CONTROL -// -static ARM_SCS_WRITEFN(writeMPU_CONTROL) { - - // update field, preserving read-only bits - Bool oldENABLE = SCS_FIELD(arm, MPU_CONTROL, ENABLE); - Bool oldHFNMIENA = SCS_FIELD(arm, MPU_CONTROL, HFNMIENA); - Bool oldPRIVDEFENA = SCS_FIELD(arm, MPU_CONTROL, PRIVDEFENA); - UPDATE_SCS_MASKED(arm, MPU_CONTROL, newValue); - Bool newENABLE = SCS_FIELD(arm, MPU_CONTROL, ENABLE); - Bool newHFNMIENA = SCS_FIELD(arm, MPU_CONTROL, HFNMIENA); - Bool newPRIVDEFENA = SCS_FIELD(arm, MPU_CONTROL, PRIVDEFENA); - - // mode switch may be required - if((oldENABLE!=newENABLE) || (oldHFNMIENA!=newHFNMIENA)) { - armSwitchMode(arm); - } - - // if PRIVDEFENA has been *cleared*, the privileged mode MPU must be - // refilled - if(oldPRIVDEFENA && !newPRIVDEFENA) { - armVMFlushMPUPriv(arm); - } -} - -// -// Write MPU_RNR -// -static ARM_SCS_WRITEFN(writeMPU_RNR) { - - // out-of-range writes to this register are ignored - if(validRegion(arm, newValue)) { - SCS_REG_UNS32(arm, MPU_RNR) = newValue; - } -} - -// -// Read MPU_RBAR -// -static ARM_SCS_READFN(readMPU_RBAR) { - - Uns32 region = SCS_FIELD(arm, MPU_RNR, REGION); - - // use union to assemble composed value - union {Uns32 u32; SCS_REG_DECL(MPU_RBAR);} u = { - armVMReadRBAR(arm, region, True) - }; - - // MPU_RBAR.VALID is RAZ - u.MPU_RBAR.VALID = 0; - - // MPU_RBAR.REGION is an alias of MPU_RNR.REGION - u.MPU_RBAR.REGION = SCS_FIELD(arm, MPU_RNR, REGION); - - // return composed value - return u.u32; -} - -// -// Write MPU_RBAR -// -static ARM_SCS_WRITEFN(writeMPU_RBAR) { - - Uns32 region; - - // use union to extract value fields - union {Uns32 u32; SCS_REG_DECL(MPU_RBAR);} u = {newValue}; - - // update region if valid and in range, and get the region to update - if(u.MPU_RBAR.VALID && validRegion(arm, u.MPU_RBAR.REGION)) { - region = SCS_FIELD(arm, MPU_RNR, REGION) = u.MPU_RBAR.REGION; - } else { - region = SCS_FIELD(arm, MPU_RNR, REGION); - } - - // update the region - armVMWriteRBAR(arm, region, True, newValue); -} - -// -// Read MPU_RASR -// -static ARM_SCS_READFN(readMPU_RASR) { - - // derive region number, allowing for alias offset - Uns32 region = SCS_FIELD(arm, MPU_RNR, REGION); - - return armVMReadRASR(arm, region, True); -} - -// -// Write MPU_RASR -// -static ARM_SCS_WRITEFN(writeMPU_RASR) { - - // derive region number, allowing for alias offset - Uns32 region = SCS_FIELD(arm, MPU_RNR, REGION); - - armVMWriteRASR(arm, region, True, newValue); -} - -// -// Read ICSR -// -static ARM_SCS_READFN(readICSR) { - - // use union to assemble composed value - union {Uns32 u32; SCS_REG_DECL(ICSR);} u = {0}; - - // seed exception number fields - u.ICSR.VECTACTIVE = PSR_FIELD(arm, exceptNum); - u.ICSR.ISRPENDING = arm->pendingInterrupt; - u.ICSR.VECTPENDING = arm->pendingException; - - // seed pending fields - u.ICSR.PENDSTSET = isPending(arm, AEN_SysTick); - u.ICSR.PENDSVSET = isPending(arm, AEN_PendSV); - u.ICSR.NMIPENDSET = isPending(arm, AEN_NMI); - - // seed RETTOBASE - u.ICSR.RETTOBASE = armGetRetToBase(arm); - - // return composed value - return u.u32; -} - -// -// Write ICSR -// -static ARM_SCS_WRITEFN(writeICSR) { - - // use union to extract value fields - union {Uns32 u32; SCS_REG_DECL(ICSR);} u = {newValue}; - - // raise NMI - if(u.ICSR.NMIPENDSET) { - setPending(arm, AEN_NMI, 1); - } - - // raise/clear PendSV - if(u.ICSR.PENDSVSET) { - setPending(arm, AEN_PendSV, 1); - } else if(u.ICSR.PENDSVCLR) { - setPending(arm, AEN_PendSV, 0); - } - - // raise/clear SysTick - if(u.ICSR.PENDSTSET) { - setPending(arm, AEN_SysTick, 1); - } else if(u.ICSR.PENDSTCLR) { - setPending(arm, AEN_SysTick, 0); - } - - // refresh any pending exception state - armRefreshPendingException(arm); -} - -// -// Read AIRCR -// -static ARM_SCS_READFN(readAIRCR) { - - // VECTKEY field has a fixed magic value - SCS_FIELD(arm, AIRCR, VECTKEY) = 0xfa05; - - // return composed value - return SCS_REG_UNS32(arm, AIRCR); -} - -// -// Write AIRCR -// -static ARM_SCS_WRITEFN(writeAIRCR) { - - // use union to extract value fields - union {Uns32 u32; SCS_REG_DECL(AIRCR);} u = {newValue}; - - // update only on magic code match - if(u.AIRCR.VECTKEY == 0x05fa) { - - // update PRIGROUP if required - if(SCS_FIELD(arm, AIRCR, PRIGROUP) != u.AIRCR.PRIGROUP) { - SCS_FIELD(arm, AIRCR, PRIGROUP) = u.AIRCR.PRIGROUP; - armRefreshExecutionPriorityPendingException(arm); - } - - // assert interrupt request if required - SCS_FIELD(arm, AIRCR, SYSRESETREQ) = u.AIRCR.SYSRESETREQ; - if(SCS_FIELD(arm, AIRCR, SYSRESETREQ)) { - writeNet(arm, arm->sysResetReq, 1); - } - } -} - -// -// Write CCR -// -static ARM_SCS_WRITEFN(writeCCR) { - - // update field, preserving read-only bits - Bool oldUnalignedTrap = SCS_FIELD(arm, CCR, UNALIGN_TRP); - UPDATE_SCS_MASKED(arm, CCR, newValue); - Bool newUnalignedTrap = SCS_FIELD(arm, CCR, UNALIGN_TRP); - - // modify blockMask if anligned access trap has changed - if(oldUnalignedTrap!=newUnalignedTrap) { - - // if this is the first time that unaligned accesses have been enabled - // or disabled, discard the current code dictionaries (they need to be - // regenerated with unaligned access checking enabled in the block mask) - if(!arm->checkUnaligned) { - vmirtFlushAllDicts((vmiProcessorP)arm); - arm->checkUnaligned = True; - } - - // refresh block mask - armSetBlockMask(arm); - } -} - -// -// Write CFSR -// NOTE: register has W1C (write-1-to-clear) semantics -// -static ARM_SCS_WRITEFN(writeCFSR) { - SCS_REG_UNS32(arm, CFSR) &= ~newValue; -} - -// -// Write HFSR -// NOTE: register has W1C (write-1-to-clear) semantics -// -static ARM_SCS_WRITEFN(writeHFSR) { - SCS_REG_UNS32(arm, HFSR) &= ~newValue; -} - -// -// Write CPACR register value -// -static ARM_SCS_WRITEFN(writeCPACR) { - - // get original register value and writable mask - Uns32 oldValue = SCS_REG_UNS32(arm, CPACR); - Uns32 mask = SCS_MASK_UNS32(arm, CPACR); - - // set the new register value, allowing for writable bits - SCS_REG_UNS32(arm, CPACR) = ((oldValue&~mask) | (newValue&mask)); - - // update blockMask to reflect enabled or disabled coprocessors - armSetBlockMask(arm); -} - -// -// Write FPCCR register value -// -static ARM_SCS_WRITEFN(writeFPCCR) { - - // update register, preserving read-only bits - Uns32 oldBMValue = SCS_REG_UNS32(arm, FPCCR) & SCS_BLOCKMASK_FPCCR; - UPDATE_SCS_MASKED(arm, FPCCR, newValue); - Uns32 newBMValue = SCS_REG_UNS32(arm, FPCCR) & SCS_BLOCKMASK_FPCCR; - - // refresh blockMask if any bits included in block mask have changed - if(oldBMValue!=newBMValue) { - armSetBlockMask(arm); - } -} - -// -// Read SYST_CSR -// -static ARM_SCS_READFN(readSYST_CSR) { - return armReadSYST_CSR(arm); -} - -// -// Write SYST_CSR -// -static ARM_SCS_WRITEFN(writeSYST_CSR) { - armWriteSYST_CSR(arm, newValue); -} - -// -// Write SYST_RVR -// -static ARM_SCS_WRITEFN(writeSYST_RVR) { - armWriteSYST_RVR(arm, newValue); -} - -// -// Read SYST_CVR -// -static ARM_SCS_READFN(readSYST_CVR) { - return armReadSYST_CVR(arm); -} - -// -// Write SYST_CVR -// NOTE: value written is always zero (supplied value is ignored) -// -static ARM_SCS_WRITEFN(writeSYST_CVR) { - armWriteSYST_CVR(arm, 0); -} - -// -// Read SHCSR -// -static ARM_SCS_READFN(readSHCSR) { - - // use union to assemble composed value - union {Uns32 u32; SCS_REG_DECL(SHCSR);} u = {0}; - - // seed enable fields - u.SHCSR.USGFAULTENA = isEnabled(arm, AEN_UsageFault); - u.SHCSR.BUSFAULTENA = isEnabled(arm, AEN_BusFault); - u.SHCSR.MEMFAULTENA = isEnabled(arm, AEN_MemManage); - - // seed pending fields - u.SHCSR.SVCALLPENDED = isPending(arm, AEN_SVCall); - u.SHCSR.USGFAULTPENDED = isPending(arm, AEN_UsageFault); - u.SHCSR.BUSFAULTPENDED = isPending(arm, AEN_BusFault); - u.SHCSR.MEMFAULTPENDED = isPending(arm, AEN_MemManage); - - // seed active fields - u.SHCSR.SYSTICKACT = isActive(arm, AEN_SysTick); - u.SHCSR.PENDSVACT = isActive(arm, AEN_PendSV); - u.SHCSR.MONITORACT = isActive(arm, AEN_DebugMonitor); - u.SHCSR.SVCALLACT = isActive(arm, AEN_SVCall); - u.SHCSR.USGFAULTACT = isActive(arm, AEN_UsageFault); - u.SHCSR.BUSFAULTACT = isActive(arm, AEN_BusFault); - u.SHCSR.MEMFAULTACT = isActive(arm, AEN_MemManage); - - // return composed value - return u.u32; -} - -// -// Write SHCSR -// -static ARM_SCS_WRITEFN(writeSHCSR) { - - // use union to extract value fields - union {Uns32 u32; SCS_REG_DECL(SHCSR);} u = {newValue}; - - // extract enable fields - setEnabled(arm, AEN_UsageFault, u.SHCSR.USGFAULTENA); - setEnabled(arm, AEN_BusFault, u.SHCSR.BUSFAULTENA); - setEnabled(arm, AEN_MemManage, u.SHCSR.MEMFAULTENA); - - // extract pending fields - setPending(arm, AEN_SVCall, u.SHCSR.SVCALLPENDED); - setPending(arm, AEN_UsageFault, u.SHCSR.USGFAULTPENDED); - setPending(arm, AEN_BusFault, u.SHCSR.BUSFAULTPENDED); - setPending(arm, AEN_MemManage, u.SHCSR.MEMFAULTPENDED); - - // extract active fields - setActive(arm, AEN_SysTick, u.SHCSR.SYSTICKACT); - setActive(arm, AEN_PendSV, u.SHCSR.PENDSVACT); - setActive(arm, AEN_DebugMonitor, u.SHCSR.MONITORACT); - setActive(arm, AEN_SVCall, u.SHCSR.SVCALLACT); - setActive(arm, AEN_UsageFault, u.SHCSR.USGFAULTACT); - setActive(arm, AEN_BusFault, u.SHCSR.BUSFAULTACT); - setActive(arm, AEN_MemManage, u.SHCSR.MEMFAULTACT); - - // refresh any pending exception state - armRefreshPendingException(arm); -} - -// -// Common routine for SHPR/NVIC_IPR read -// -static Uns32 readPriority(armP arm, Uns32 byteOffset) { - - if(byteOffsetexceptNum) { - return *(Uns32 *)(&arm->xPriority[byteOffset]); - } else { - return 0; - } -} - -// -// Common routine for SHPR/NVIC_IPR write -// -static void writePriority(armP arm, Uns32 byteOffset, Uns32 newValue) { - - if(byteOffsetexceptNum) { - - // priority value must be masked to the supported bits - newValue &= arm->priorityMask; - - // get indexed value in priority array - Uns32 *valueP = (Uns32 *)(&arm->xPriority[byteOffset]); - - // update priority entry if required - if(newValue != *valueP) { - *valueP = newValue; - armRefreshExecutionPriorityPendingException(arm); - } - } -} - -// -// Read SHPR1 -// -static ARM_SCS_READFN(readSHPR1) { - return readPriority(arm, 4); -} - -// -// Write SHPR1 -// -static ARM_SCS_WRITEFN(writeSHPR1) { - writePriority(arm, 4, newValue & SCS_WRITE_MASK_SHPR1); -} - -// -// Read SHPR2 -// -static ARM_SCS_READFN(readSHPR2) { - return readPriority(arm, 8); -} - -// -// Write SHPR2 -// -static ARM_SCS_WRITEFN(writeSHPR2) { - writePriority(arm, 8, newValue & SCS_WRITE_MASK_SHPR2); -} - -// -// Read SHPR3 -// -static ARM_SCS_READFN(readSHPR3) { - return readPriority(arm, 12); -} - -// -// Write SHPR3 -// -static ARM_SCS_WRITEFN(writeSHPR3) { - writePriority(arm, 12, newValue & SCS_WRITE_MASK_SHPR3); -} - -// -// Write STIR -// NOTE: this can be made accessible to user mode -// -static ARM_SCS_WRITEFN(writeSTIR) { - - // use union to extract value fields - union {Uns32 u32; SCS_REG_DECL(STIR);} u = {newValue}; - Uns32 exceptionNum = u.STIR.INTID + AEN_ExternalInt0; - - // ensure interrupt is within bounds - if(exceptionNumexceptNum) { - - // raise the exception - setPending(arm, exceptionNum, 1); - - // refresh any pending exception state - armRefreshPendingException(arm); - } -} - -// -// Return a composed value from an interrupt mask register -// -static Uns32 readIntReg(armP arm, Uns32 *reg, Uns32 byteOffset) { - - Uns32 wordOffset = byteOffset*4; - Uns32 result = 0; - - // validate interrupt register is in bounds - if(wordOffsetexceptMaskNum) { - - // get lower half of the result - result = reg[wordOffset] >> AEN_ExternalInt0; - - // upper half is extracted only if this is not the last entry - if(wordOffset!=(arm->exceptMaskNum-1)) { - result |= reg[wordOffset+1] << (32-AEN_ExternalInt0); - } - } - - return result; -} - -// -// Add one-bits from the passed value into the register -// -static void setIntReg(armP arm, Uns32 *reg, Uns32 byteOffset, Uns32 newValue) { - - Uns32 wordOffset = byteOffset*4; - - // validate interrupt register is in bounds - if(wordOffsetexceptMaskNum) { - - // set lower half of the result - reg[wordOffset] |= (newValue << AEN_ExternalInt0); - - // upper half is set only if this is not the last entry - if(wordOffset!=(arm->exceptMaskNum-1)) { - reg[wordOffset+1] |= (newValue >> (32-AEN_ExternalInt0)); - } - - // refresh any pending exception state - armRefreshPendingException(arm); - } -} - -// -// Remove one-bits from the passed value into the register -// -static void clearIntReg(armP arm, Uns32 *reg, Uns32 byteOffset, Uns32 newValue) { - - Uns32 wordOffset = byteOffset*4; - - // validate interrupt register is in bounds - if(wordOffsetexceptMaskNum) { - - // set lower half of the result - reg[wordOffset] &= ~(newValue << AEN_ExternalInt0); - - // upper half is set only if this is not the last entry - if(wordOffset!=(arm->exceptMaskNum-1)) { - reg[wordOffset+1] &= ~(newValue >> (32-AEN_ExternalInt0)); - } - - // refresh any pending exception state - armRefreshPendingException(arm); - } -} - -// -// Read NVIC_ISER -// -static ARM_SCS_READFN(readNVIC_ISER) { - return readIntReg(arm, arm->xEnable, byteOffset); -} - -// -// Write NVIC_ISER -// -static ARM_SCS_WRITEFN(writeNVIC_ISER) { - setIntReg(arm, arm->xEnable, byteOffset, newValue); -} - -// -// Read NVIC_ICER -// -static ARM_SCS_READFN(readNVIC_ICER) { - return readIntReg(arm, arm->xEnable, byteOffset); -} - -// -// Write NVIC_ICER -// -static ARM_SCS_WRITEFN(writeNVIC_ICER) { - clearIntReg(arm, arm->xEnable, byteOffset, newValue); -} - -// -// Read NVIC_ISPR -// -static ARM_SCS_READFN(readNVIC_ISPR) { - return readIntReg(arm, arm->xPend, byteOffset); -} - -// -// Write NVIC_ISPR -// -static ARM_SCS_WRITEFN(writeNVIC_ISPR) { - setIntReg(arm, arm->xPend, byteOffset, newValue); -} - -// -// Read NVIC_ICPR -// -static ARM_SCS_READFN(readNVIC_ICPR) { - return readIntReg(arm, arm->xPend, byteOffset); -} - -// -// Write NVIC_ICPR -// -static ARM_SCS_WRITEFN(writeNVIC_ICPR) { - clearIntReg(arm, arm->xPend, byteOffset, newValue); -} - -// -// Read NVIC_IABR -// -static ARM_SCS_READFN(readNVIC_IABR) { - return readIntReg(arm, arm->xActive, byteOffset); -} - -// -// Read NVIC_IPR -// -static ARM_SCS_READFN(readNVIC_IPR) { - return readPriority(arm, byteOffset+AEN_ExternalInt0); -} - -// -// Write NVIC_IPR -// -static ARM_SCS_WRITEFN(writeNVIC_IPR) { - writePriority(arm, byteOffset+AEN_ExternalInt0, newValue); -} - - -//////////////////////////////////////////////////////////////////////////////// -// RESET AND INITIALIZATION -//////////////////////////////////////////////////////////////////////////////// - -// -// Macro used to set initial value of read-only system register from configuration -// -#define INITIALIZE_SCS_REG(_P, _N) \ - SCS_REG_STRUCT(_P, _N) = SCS_REG_STRUCT_DEFAULT(_P, _N) - -// -// Macro used to set initial value of read-only system field from configuration -// -#define INITIALIZE_SCS_FIELD(_P, _N, _F) \ - SCS_FIELD(_P, _N, _F) = SCS_FIELD_DEFAULT(_P, _N, _F) - -// -// Macro use to force reset of a system register to a fixed initial value -// -#define RESET_SCS_REG_VALUE(_P, _R, _V) \ - armWriteSysRegPriv(SCS_ID(_R), _P, _V) - -// -// Macro use to force reset of a system register to its initial configured state -// -#define RESET_SCS_REG_CONFIG(_P, _R) { \ - union {SCS_REG_DECL(_R); Uns32 u32;} u = {SCS_REG_STRUCT_DEFAULT(_P, _R)}; \ - RESET_SCS_REG_VALUE(_P, _R, u.u32); \ -} - -// -// Call on initialization -// -void armSysInitialize(armP arm) { - - // initialize SCS registers that are directly represented - INITIALIZE_SCS_REG(arm, ICTR); - INITIALIZE_SCS_REG(arm, CPUID); - INITIALIZE_SCS_REG(arm, SYST_CALIB); - INITIALIZE_SCS_REG(arm, ID_PFR0); - INITIALIZE_SCS_REG(arm, ID_PFR1); - INITIALIZE_SCS_REG(arm, ID_DFR0); - INITIALIZE_SCS_REG(arm, ID_AFR0); - INITIALIZE_SCS_REG(arm, ID_MMFR0); - INITIALIZE_SCS_REG(arm, ID_MMFR1); - INITIALIZE_SCS_REG(arm, ID_MMFR2); - INITIALIZE_SCS_REG(arm, ID_MMFR3); - INITIALIZE_SCS_REG(arm, ID_ISAR0); - INITIALIZE_SCS_REG(arm, ID_ISAR1); - INITIALIZE_SCS_REG(arm, ID_ISAR2); - INITIALIZE_SCS_REG(arm, ID_ISAR3); - INITIALIZE_SCS_REG(arm, ID_ISAR4); - INITIALIZE_SCS_REG(arm, ID_ISAR5); - INITIALIZE_SCS_REG(arm, MVFR0); - INITIALIZE_SCS_REG(arm, MVFR1); - INITIALIZE_SCS_REG(arm, MPU_TYPE); - - // configure permanently-enabled exceptions - arm->xEnable[0] = ARM_EXCEPT_PERMANENT_ENABLE; - - // ICTR.INTLINESNUM depends on the number of configured interrupts - SCS_FIELD(arm, ICTR, INTLINESNUM) = NUM_INTERRUPTS(arm)/32; -} - -// -// Call on reset -// -void armSysReset(armP arm) { - - Uns32 i; - - // reset SCS registers that are directly represented - RESET_SCS_REG_CONFIG(arm, ACTLR); - RESET_SCS_REG_CONFIG(arm, CPACR); - RESET_SCS_REG_VALUE (arm, ICSR, 0x00000000); - RESET_SCS_REG_VALUE (arm, VTOR, 0x00000000); - RESET_SCS_REG_VALUE (arm, AIRCR, 0x05fa0000); - RESET_SCS_REG_VALUE (arm, SCR, 0x00000000); - RESET_SCS_REG_VALUE (arm, CCR, 0x00000200); - RESET_SCS_REG_VALUE (arm, SHCSR, 0x00000000); - RESET_SCS_REG_VALUE (arm, CFSR, 0xffffffff); - RESET_SCS_REG_VALUE (arm, HFSR, 0x00000000); - RESET_SCS_REG_VALUE (arm, SYST_CSR, 0x00000000); - RESET_SCS_REG_VALUE (arm, FPCCR, 0xc0000000); - RESET_SCS_REG_VALUE (arm, FPCAR, 0x00000000); - RESET_SCS_REG_VALUE (arm, FPDSCR, 0x00000000); - - arm->FPCARdomain = NULL; - - // reset exception pending and enable masks - for(i=0; iexceptMaskNum; i++) { - arm->xPend [i] = 0; - arm->xEnable[i] = 0; - } - - // reset exception priority numbers - for(i=0; iexceptNum; i++) { - arm->xPriority[i] = 0; - } - - // configure permanently-enabled exceptions - arm->xEnable[0] = ARM_EXCEPT_PERMANENT_ENABLE; -} - - -//////////////////////////////////////////////////////////////////////////////// -// SYSTEM REGISTER ACCESS -//////////////////////////////////////////////////////////////////////////////// - -// -// PPB address range -// -#define PPB_LOW 0xe0000000 -#define PPB_HIGH 0xe00fffff - -// -// System space base address -// -#define SCS_BASE 0xe000e000 - -// -// Type used to return information enabling a system register to be read -// -typedef struct armSCSReadInfoS { - vmiReg rs; // if the register can be read by a simple access - armSCSReadFn cb; // if the read requires a callback - armSysRegDesc regDesc; // regDesc for read callback -} armSCSReadInfo, *armSCSReadInfoP; - -// -// Type used to return information enabling a system register to be written -// -typedef struct armSCSWriteInfoS { - vmiReg rd; // if the register can be written by a simple access - armSCSWriteFn cb; // if the write requires a callback - armSysRegDesc regDesc; // regDesc for write callback - Uns32 writeMask;// mask of writable bits in this register -} armSCSWriteInfo, *armSCSWriteInfoP; - -// -// Type enumerating the units for which system registers are present -// -typedef enum armUnitE { - AU_ALL, // always present - AU_MPU, // present for cores with MPU only - AU_USM, // access possible in user mode if CCR.USERSETMPEND - AU_FPU, // access possible if FPU implemented -} armUnit; - -// -// Type enumerating classes of access to register -// -typedef enum accessActionE { - - AA_READ = 0x0, - AA_WRITE = 0x1, - AA_PRIV = 0x0, - AA_USER = 0x2, - - AA_PRIV_READ = AA_READ | AA_PRIV, // privileged mode read - AA_PRIV_WRITE = AA_WRITE | AA_PRIV, // privileged mode write - AA_USER_READ = AA_READ | AA_USER, // user mode read - AA_USER_WRITE = AA_WRITE | AA_USER, // user mode write - - AA_LAST - -} accessAction; - -// -// Descr strings for accessAction values -// -static const char *accessActionRW[2][2] = { - {"--", "-w"}, - {"r-", "rw"}, -}; - -// -// This structure records information about each system register -// -typedef struct scsRegAttrsS { - const char *name; - Bool access[AA_LAST]; - armUnit unit; - armSCSReadFn readCB; - armSCSWriteFn writeCB; - Uns32 writeMask; - Uns32 address; - Uns32 numWords; -} scsRegAttrs; - -// -// Macro to initialize one-word entry in scsRegInfo -// -#define SCS_ATTR(_ID, _PR,_PW,_UR,_UW, _UNIT, _READCB, _WRITECB) \ - [SCS_ID(_ID)] = { \ - name : #_ID, \ - access : {_PR,_PW,_UR,_UW}, \ - unit : _UNIT, \ - readCB : _READCB, \ - writeCB : _WRITECB, \ - writeMask : SCS_WRITE_MASK_##_ID, \ - address : SCS_BASE | SCS_ADDRESS_##_ID, \ - numWords : 1 \ - } - -// -// Macro to initialize multi-word entry in scsRegInfo -// -#define SCS_ATTR_N(_ID, _N, _PR,_PW,_UR,_UW, _UNIT, _READCB, _WRITECB) \ - [SCS_ID(_ID##x##_N)] = { \ - name : #_ID"x"#_N, \ - access : {_PR,_PW,_UR,_UW}, \ - unit : _UNIT, \ - readCB : _READCB, \ - writeCB : _WRITECB, \ - writeMask : SCS_WRITE_MASK_##_ID, \ - address : SCS_BASE | SCS_ADDRESS_##_ID, \ - numWords : _N \ - } - -// -// Table of system register attributes -// -const static scsRegAttrs scsRegInfo[SCS_ID(Size)] = { - - //////////////////////////////////////////////////////////////////////////// - // true registers (represented in processor structure) - //////////////////////////////////////////////////////////////////////////// - - // id access unit readCB writeCB - SCS_ATTR( ICTR, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ACTLR, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( CPUID, 1,0,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( VTOR, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( AIRCR, 1,1,0,0, AU_ALL, readAIRCR, writeAIRCR ), - SCS_ATTR( SCR, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( CCR, 1,1,0,0, AU_ALL, 0, writeCCR ), - SCS_ATTR( CFSR, 1,1,0,0, AU_ALL, 0, writeCFSR ), - SCS_ATTR( HFSR, 1,1,0,0, AU_ALL, 0, writeHFSR ), - SCS_ATTR( AFSR, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( MMAR, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( BFAR, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( CPACR, 1,1,0,0, AU_ALL, 0, writeCPACR ), - - // id access unit readCB writeCB - SCS_ATTR( SYST_CSR, 1,1,0,0, AU_ALL, readSYST_CSR, writeSYST_CSR ), - SCS_ATTR( SYST_RVR, 1,1,0,0, AU_ALL, 0, writeSYST_RVR ), - SCS_ATTR( SYST_CVR, 1,1,0,0, AU_ALL, readSYST_CVR, writeSYST_CVR ), - SCS_ATTR( SYST_CALIB, 1,1,0,0, AU_ALL, 0, 0 ), - - // id access unit readCB writeCB - SCS_ATTR( ID_PFR0, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_PFR1, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_DFR0, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_AFR0, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_MMFR0, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_MMFR1, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_MMFR2, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_MMFR3, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_ISAR0, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_ISAR1, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_ISAR2, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_ISAR3, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_ISAR4, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( ID_ISAR5, 1,1,0,0, AU_ALL, 0, 0 ), - - // id access unit readCB writeCB - SCS_ATTR( FPCCR, 1,1,0,0, AU_FPU, 0, writeFPCCR ), - SCS_ATTR( FPCAR, 1,1,0,0, AU_FPU, 0, 0 ), - SCS_ATTR( FPDSCR, 1,1,0,0, AU_FPU, 0, 0 ), - SCS_ATTR( MVFR0, 1,0,0,0, AU_FPU, 0, 0 ), - SCS_ATTR( MVFR1, 1,0,0,0, AU_FPU, 0, 0 ), - - // id access unit readCB writeCB - SCS_ATTR( MPU_TYPE, 1,1,0,0, AU_ALL, 0, 0 ), - SCS_ATTR( MPU_CONTROL, 1,1,0,0, AU_ALL, 0, writeMPU_CONTROL), - SCS_ATTR( MPU_RNR, 1,1,0,0, AU_ALL, 0, writeMPU_RNR ), - - //////////////////////////////////////////////////////////////////////////// - // pseudo-registers (not represented in processor structure) - //////////////////////////////////////////////////////////////////////////// - - // id access unit readCB writeCB - SCS_ATTR( ICSR, 1,1,0,0, AU_ALL, readICSR, writeICSR ), - SCS_ATTR( SHCSR, 1,1,0,0, AU_ALL, readSHCSR, writeSHCSR ), - - // id access unit readCB writeCB - SCS_ATTR( SHPR1, 1,1,0,0, AU_ALL, readSHPR1, writeSHPR1 ), - SCS_ATTR( SHPR2, 1,1,0,0, AU_ALL, readSHPR2, writeSHPR2 ), - SCS_ATTR( SHPR3, 1,1,0,0, AU_ALL, readSHPR3, writeSHPR3 ), - SCS_ATTR( STIR, 1,1,1,1, AU_USM, ignoreSysRead, writeSTIR ), - - // id num access unit readCB writeCB - SCS_ATTR_N(NVIC_ISER, 16, 1,1,0,0, AU_ALL, readNVIC_ISER, writeNVIC_ISER ), - SCS_ATTR_N(NVIC_ICER, 16, 1,1,0,0, AU_ALL, readNVIC_ICER, writeNVIC_ICER ), - SCS_ATTR_N(NVIC_ISPR, 16, 1,1,0,0, AU_ALL, readNVIC_ISPR, writeNVIC_ISPR ), - SCS_ATTR_N(NVIC_ICPR, 16, 1,1,0,0, AU_ALL, readNVIC_ICPR, writeNVIC_ICPR ), - SCS_ATTR_N(NVIC_IABR, 16, 1,1,0,0, AU_ALL, readNVIC_IABR, ignoreSysWrite ), - SCS_ATTR_N(NVIC_IPR, 255, 1,1,0,0, AU_ALL, readNVIC_IPR, writeNVIC_IPR ), - - // id access unit readCB writeCB - SCS_ATTR( MPU_RBAR, 1,1,0,0, AU_MPU, readMPU_RBAR, writeMPU_RBAR ), - SCS_ATTR( MPU_RASR, 1,1,0,0, AU_MPU, readMPU_RASR, writeMPU_RASR ), - SCS_ATTR( MPU_RBAR_A1, 1,1,0,0, AU_MPU, readMPU_RBAR, writeMPU_RBAR ), - SCS_ATTR( MPU_RASR_A1, 1,1,0,0, AU_MPU, readMPU_RASR, writeMPU_RASR ), - SCS_ATTR( MPU_RBAR_A2, 1,1,0,0, AU_MPU, readMPU_RBAR, writeMPU_RBAR ), - SCS_ATTR( MPU_RASR_A2, 1,1,0,0, AU_MPU, readMPU_RASR, writeMPU_RASR ), - SCS_ATTR( MPU_RBAR_A3, 1,1,0,0, AU_MPU, readMPU_RBAR, writeMPU_RBAR ), - SCS_ATTR( MPU_RASR_A3, 1,1,0,0, AU_MPU, readMPU_RASR, writeMPU_RASR ) -}; - -// -// Iterator filling 'desc' with the next system register description - -// 'desc.name' should be initialized to NULL prior to the first call -// -Bool armGetSysRegisterDesc(armSysRegDescP desc) { - - armSCSRegId id = desc->name ? desc->id+1 : 0; - - if(id>=SCS_ID(FirstPseudoReg)) { - - return False; - - } else { - - const scsRegAttrs *attrs = &scsRegInfo[id]; - - desc->name = attrs->name; - desc->id = id; - desc->address = attrs->address; - desc->privRW = accessActionRW[attrs->access[AA_PRIV_READ]][attrs->access[AA_PRIV_WRITE]]; - desc->userRW = accessActionRW[attrs->access[AA_USER_READ]][attrs->access[AA_USER_WRITE]]; - - return True; - } -} - -// -// Can the indicated system register be accessed using the passed action on -// this ARM processor variant? -// -static Bool canAccessSysReg( - armP arm, - const scsRegAttrs *attrs, - accessAction action -) { - if(!attrs->access[action]) { - return False; - } else switch(attrs->unit) { - case AU_MPU: return MPU_PRESENT(arm); - case AU_USM: return !(action&AA_USER) || SCS_FIELD(arm, CCR, USERSETMPEND); - case AU_FPU: return FPU_PRESENT(arm); - default: return True; - } -} - -// -// Fill armSCSReadInfo structure with information about how to perform a system -// register read -// -static Bool getSysReadInfo( - armP arm, - armSCSReadInfoP info, - armSCSRegId id, - accessAction action -) { - info->rs = VMI_NOREG; - - if(id==SCS_ID(INVALID)) { - - // invalid register access - info->cb = ignoreSysRead; - - } else { - - // read of plain register or by callback - if(scsRegInfo[id].readCB) { - info->cb = scsRegInfo[id].readCB; - } else if(idrs = ARM_SCS_REG(id); - } - } - - return True; -} - -// -// Fill armSCSWriteInfo structure with information about how to perform a -// system register write -// -static Bool getSysWriteInfo( - armP arm, - armSCSWriteInfoP info, - Uns32 id, - accessAction action -) { - info->rd = VMI_NOREG; - - if(id==SCS_ID(INVALID)) { - - // invalid register access - info->cb = ignoreSysWrite; - - } else { - - // write of plain register or by callback - if(scsRegInfo[id].writeCB) { - info->cb = scsRegInfo[id].writeCB; - } else if(idrd = ARM_SCS_REG(id); - } - - // get mask of writable bits - info->writeMask = scsRegInfo[id].writeMask; - } - - return True; -} - -// -// Return a value read from a fixed offset in the processor structure -// -static ARM_SCS_READFN(readSCS) { - return arm->scs.regs[id]; -} - -// -// Write a value to a fixed offset in the processor structure -// -static ARM_SCS_WRITEFN(writeSCS) { - - Uns32 writeMask = scsRegInfo[id].writeMask; - Uns32 oldValue = arm->scs.regs[id]; - - arm->scs.regs[id] = ((oldValue&~writeMask) | (newValue&writeMask)); -} - -// -// Is the indicated system register supported on this processor? -// -Bool armGetSysRegSupported(armSCSRegId id, armP arm) { - - const scsRegAttrs *attrs = &scsRegInfo[id]; - - return ( - canAccessSysReg(arm, attrs, AA_PRIV_READ) || - canAccessSysReg(arm, attrs, AA_PRIV_WRITE) - ); -} - -// -// Get system register read callback (privileged mode) -// -static armSCSReadFn getSysPrivRegReadCallBack(armSCSRegId id, armP arm) { - - accessAction action = AA_PRIV_READ; - const scsRegAttrs *attrs = &scsRegInfo[id]; - armSCSReadInfo info = {regDesc : {id:id}}; - - if(!canAccessSysReg(arm, attrs, action)) { - return 0; - } else if(!getSysReadInfo(arm, &info, id, action)) { - return 0; - } else if(info.cb) { - return info.cb; - } else if(!VMI_ISNOREG(info.rs)) { - return readSCS; - } else { - return 0; - } -} - -// -// Get system register write callback (privileged mode) -// -static armSCSWriteFn getSysPrivRegWriteCallBack(armSCSRegId id, armP arm) { - - accessAction action = AA_PRIV_WRITE; - const scsRegAttrs *attrs = &scsRegInfo[id]; - armSCSWriteInfo info = {regDesc : {id:id}}; - - if(!canAccessSysReg(arm, attrs, action)) { - return 0; - } else if(!getSysWriteInfo(arm, &info, id, action)) { - return 0; - } else if(info.cb) { - return info.cb; - } else if(!VMI_ISNOREG(info.rd)) { - return writeSCS; - } else { - return 0; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// INSERT SYSTEM REGISTERS INTO DOMAIN -//////////////////////////////////////////////////////////////////////////////// - -// -// Callback function to write a system register -// -static VMI_MEM_WRITE_FN(writeSys) { - - if(processor) { - - armP arm = (armP)processor; - const scsRegAttrs *attrs = userData; - armSCSRegId id = attrs-scsRegInfo; - Uns32 offset = address - attrs->address; - Uns32 writeMask = attrs->writeMask; - Bool bigEndian = SCS_FIELD(arm, AIRCR, ENDIANNESS); - Uns32 newValue; - - // get the value to write (may be partial register) - if(bytes==1) { - newValue = *(Uns8*)value; - } else if(bytes==2) { - newValue = SWAP_2_BYTE_COND(*(Uns16*)value, bigEndian); - } else if(bytes==4) { - newValue = SWAP_4_BYTE_COND(*(Uns32*)value, bigEndian); - } else { - VMI_ABORT("unimplemented system register size %u bytes", bytes); - } - - if(IN_USER_MODE(arm) && !canAccessSysReg(arm, attrs, AA_USER_WRITE)) { - - // no access to this register in user mode - armBusFault(arm, address, MEM_PRIV_W); - - } else if(attrs->writeCB) { - - // detect partial register write - if((offset&3) || (bytes!=4)) { - - // access within register - do read-modify-write of entire 4-byte - // register - Uns32 offset4 = offset&~3; - Uns32 oldValue; - Uns32 i; - - // get 4-byte value, either directly or by callback - if(attrs->readCB) { - oldValue = attrs->readCB(arm, id, offset4); - } else { - oldValue = arm->scs.regs[id]; - } - - // get 4-byte value with its mask - union {Uns32 u32; Uns8 u8[4];} uValue = {oldValue}; - union {Uns32 u32; Uns8 u8[4];} uMask = {writeMask}; - - // update writable bits in the subrange - for(i=offset; i>= 8; - } - - // put back the modified value - attrs->writeCB(arm, id, uValue.u32, offset4); - - } else { - - // write full register - attrs->writeCB(arm, id, newValue, offset); - } - - } else { - - Uns32 *regValue = &arm->scs.regs[id]; - - // detect partial register write - if((offset&3) || (bytes!=4)) { - - // access within register - Uns8 *regValue8 = (Uns8 *)regValue; - Uns32 i; - - // align writeMask - writeMask >>= (offset*8); - - // update writable bits in the subrange - for(i=offset; i>= 8; - writeMask >>= 8; - } - - } else { - - // write full register - *regValue = ( - (*regValue & ~writeMask) | - (newValue & writeMask) - ); - } - } - } -} - -// -// Callback function to read a system register -// -static VMI_MEM_READ_FN(readSys) { - - if(processor) { - - armP arm = (armP)processor; - const scsRegAttrs *attrs = userData; - armSCSRegId id = attrs-scsRegInfo; - Uns32 offset = address - attrs->address; - Uns32 result = 0; - Bool bigEndian = SCS_FIELD(arm, AIRCR, ENDIANNESS); - - if(IN_USER_MODE(arm) && !canAccessSysReg(arm, attrs, AA_USER_READ)) { - - // no access to this register in user mode - armBusFault(arm, address, MEM_PRIV_R); - - } else if(attrs->readCB) { - - // read using callback - Uns32 offset4 = offset&~3; - Uns32 shift = (offset&3) * 8; - - result = attrs->readCB(arm, id, offset4) >> shift; - - } else { - - // read from processor structure - Uns32 *regValue = &arm->scs.regs[id]; - Uns32 offset4 = offset/4; - Uns32 shift = (offset&3) * 8; - - result = regValue[offset4] >> shift; - } - - // get the value read (may be partial register) - if(bytes==1) { - *(Uns8*)value = result; - } else if(bytes==2) { - *(Uns16*)value = SWAP_2_BYTE_COND(result, bigEndian); - } else if(bytes==4) { - *(Uns32*)value = SWAP_4_BYTE_COND(result, bigEndian); - } else { - VMI_ABORT("unimplemented system register size %u bytes", bytes); - } - } -} - -// -// Callback function to write PPB region not mapped to a system register -// -static VMI_MEM_WRITE_FN(writePPB) { - - armP arm = (armP)processor; - - if(arm && IN_USER_MODE(arm)) { - armBusFault(arm, address, MEM_PRIV_W); - } -} - -// -// Callback function to read PPB region not mapped to a system register -// -static VMI_MEM_READ_FN(readPPB) { - - armP arm = (armP)processor; - - if(arm && IN_USER_MODE(arm)) { - armBusFault(arm, address, MEM_PRIV_W); - } else if(bytes==1) { - *(Uns8*)value = 0; - } else if(bytes==2) { - *(Uns16*)value = 0; - } else if(bytes==4) { - *(Uns32*)value = 0; - } else { - VMI_ABORT("unimplemented system register size %u bytes", bytes); - } -} - -// -// Type used to record SCS register bounds -// -typedef struct SCSRegAddrS { - Uns32 lowAddr; // low address - Uns32 highAddr; // high address -} SCSRegAddr, *SCSRegAddrP; - -// -// Callback used to sort SCS register entries in ascending address -// -static Int32 compareRegAddr(const void *va, const void *vb) { - - const SCSRegAddr *a = va; - const SCSRegAddr *b = vb; - - return a->lowAddrlowAddr ? -1 : 1; -} - -// -// Insert SCS region into the passed domain at the standard location -// -void armSysCreateSCSRegion(armP arm, memDomainP domain) { - - armSCSRegId id; - SCSRegAddr scsRegAddrs[SCS_ID(Size)]; - Uns32 prevLow = PPB_LOW; - Uns32 numRegs = 0; - Uns32 i; - - // remove any existing PPB region mapping - vmirtUnaliasMemory(domain, PPB_LOW, PPB_HIGH); - - // install system registers - for(id=0; idlowAddr = attrs->address; - regAddr->highAddr = regAddr->lowAddr + attrs->numWords*4 - 1; - - // install callbacks to implement the register - vmirtMapCallbacks( - domain, regAddr->lowAddr, regAddr->highAddr, readSys, writeSys, - (void *)attrs - ); - } - } - - // sort register descriptions in ascending address order - qsort(scsRegAddrs, numRegs, sizeof(scsRegAddrs[0]), compareRegAddr); - - // fill unmapped sections in PPB region with default callback - for(i=0; ilowAddr > prevLow) { - vmirtMapCallbacks( - domain, prevLow, regAddr->lowAddr-1, readPPB, writePPB, 0 - ); - } - - prevLow = regAddr->highAddr+1; - } - - // map final PPB subregion using default callbacks - if(prevLowaddress); - - // create new register object - vmiViewObjectP regObject = vmirtAddViewObject( - baseObject, name, description - ); - - // either reference the value directly or use a callback - if(info.cb) { - vmirtSetViewObjectValueCallback(regObject, scsRegViewCB, (void *)id); - } else { - Uns32 *refValue = &arm->scs.regs[id]; - vmirtSetViewObjectRefValue(regObject, VMI_VVT_UNS32, refValue); - } - } -} - - diff --git a/simulators/ovp/armmModel/armmUtils.c b/simulators/ovp/armmModel/armmUtils.c deleted file mode 100644 index 0de184d3..00000000 --- a/simulators/ovp/armmModel/armmUtils.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// VMI header files -#include "vmi/vmiCxt.h" -#include "vmi/vmiRt.h" -#include "vmi/vmiMessage.h" - -// model header files -#include "armDecode.h" -#include "armExceptions.h" -#include "armFunctions.h" -#include "armStructure.h" -#include "armSysRegisters.h" -#include "armUtils.h" -#include "armVM.h" - -// -// Return the version of the instruction set implemented by the processor -// -inline static Uns32 getInstructionVersion(armP arm) { - return ARM_INSTRUCTION_VERSION(arm->configInfo.arch); -} - -// -// Return endianness of the processor, public routine -// -VMI_ENDIAN_FN(armGetEndian) { - - armP arm = (armP)processor; - - if(isFetch) { - return arm->instructionEndian; - } else if(SCS_FIELD(arm, AIRCR, ENDIANNESS)) { - return MEM_ENDIAN_BIG; - } else { - return MEM_ENDIAN_LITTLE; - } -} - -// -// Set the initial endianness for the model -// -void armSetInitialEndian(armP arm, Bool isBigEndian) { - SCS_FIELD(arm, AIRCR, ENDIANNESS) = isBigEndian; -} - -// -// Return the next instruction address after 'thisPC'. -// -VMI_NEXT_PC_FN(armNextInstruction) { - return (Uns32)(thisPC + armGetInstructionSize((armP)processor, thisPC)); -} - -// -// Return the name of a GPR -// -const char *armGetGPRName(armP arm, Uns32 index) { - - static const char *gprNames[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" - }; - - return gprNames[index]; -} - -// -// Return the name of a CPR -// -const char *armGetCPRName(armP arm, Uns32 index) { - - static const char *cprNames[] = { - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", - "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15" - }; - - return cprNames[index]; -} - -#define SWAP_REG(_R1, _R2) {Uns32 _V = _R1; _R1= _R2; _R2 = _V;} -#define SWAP_GPR(_N, _SET) SWAP_REG(arm->regs[_N], arm->bank.R##_N##_##_SET) - -// -// Switch banked registers on switch to the passed mode -// -inline static void switchRegs(armP arm, Bool useSPProcess) { - if(useSPProcess) { - SWAP_GPR(13, process); - } -} - -// -// Switch banked registers on switch between the passed modes -// -void armSwitchRegs(armP arm, Bool oldUseSPProcess, Bool newUseSPProcess) { - switchRegs(arm, oldUseSPProcess); - switchRegs(arm, newUseSPProcess); -} - -// -// Return current processor block mask -// -static armBlockMask getBlockMask(armP arm) { - - armBlockMask blockMask = 0; - - // get blockmask component selecting register bank - if(USE_SP_PROCESS(arm)) { - blockMask |= ARM_BM_USE_SP_PROCESS; - } - - // include component for endianness - if(SCS_FIELD(arm, AIRCR, ENDIANNESS)) { - blockMask |= ARM_BM_BIG_ENDIAN; - } - - // include component for alignment checking - if(DO_UNALIGNED(arm)) { - blockMask |= ARM_BM_UNALIGNED; - } - - // include component for cp10 (and cp11) enable checking - // NOTE: arm documentation specifies behavior is undefined if cp10 enable - // differs from cp11 enable, so only cp10 enable is checked here - Uns32 cp10Enable = SCS_FIELD(arm, CPACR, cp10); - if(IN_USER_MODE(arm)) { - if(cp10Enable&2) {blockMask |= ARM_BM_CP10;} - } else { - if(cp10Enable&1) {blockMask |= ARM_BM_CP10;} - } - - // include CONTROL.FPCA bit - if(CONTROL_FIELD(arm, FPCA)) { - blockMask |= ARM_BM_FPCA; - } - - // include FPCCR.ASPEN bit - if(SCS_FIELD(arm, FPCCR, ASPEN)) { - blockMask |= ARM_BM_ASPEN; - } - - // include FPCCR.LSPACT bit - if(SCS_FIELD(arm, FPCCR, LSPACT)) { - blockMask |= ARM_BM_LSPACT; - } - - return blockMask; -} - -// -// Update processor block mask -// -void armSetBlockMask(armP arm) { - vmirtSetBlockMask((vmiProcessorP)arm, getBlockMask(arm)); -} - -// -// Update processor mode when system state that affects it has been written -// -static void updateMode(armP arm) { - - // update block mask - armSetBlockMask(arm); - - // switch mode if required - armSwitchMode(arm); -} - -// -// Write CONTROL.SP_PROCESS field -// -void armWriteSPProcess(armP arm, Bool newUseSPProcess) { - - Bool oldUseSPProcess = USE_SP_PROCESS(arm); - - if(oldUseSPProcess!=newUseSPProcess) { - - // update CONTROL.SP_PROCESS - USE_SP_PROCESS(arm) = newUseSPProcess; - - // switch banked registers - armSwitchRegs(arm, oldUseSPProcess, newUseSPProcess); - - // update block mask - armSetBlockMask(arm); - } -} - -// -// Read CPSR register -// -Uns32 armReadCPSR(armP arm) { - - // seed flag fields from flag structure - PSR_FIELD(arm, Z) = arm->aflags.ZF; - PSR_FIELD(arm, N) = arm->aflags.NF; - PSR_FIELD(arm, C) = arm->aflags.CF; - PSR_FIELD(arm, V) = arm->aflags.VF; - PSR_FIELD(arm, Q) = arm->oflags.QF; - - // seed if-then state fields - PSR_FIELD(arm, IT10) = arm->itStateRT & 0x3; - PSR_FIELD(arm, IT72) = arm->itStateRT >> 2; - - // return derived value - return arm->sregs.PSR.reg; -} - -// -// Read CONTROL register -// -Uns32 armReadCONTROL(armP arm) { - - // return value - return arm->sregs.CONTROL.reg; -} - -// -// Write CPSR register -// -void armWriteCPSR(armP arm, Uns32 value, Uns32 mask) { - - // save current processor mode - Bool oldHandlerMode = IN_HANDLER_MODE(arm); - Bool oldCPSRT = PSR_FIELD(arm, T); - - if (!DSP_PRESENT(arm)) { - // GE fields reserved when DSP not implemented - mask &= ~PSR_GE; - } - - // set new register value (writable bits only) - arm->sregs.PSR.reg = (value & mask) | (arm->sregs.PSR.reg & ~mask); - - // get new processor mode - Bool newHandlerMode = IN_HANDLER_MODE(arm); - Bool newCPSRT = PSR_FIELD(arm, T); - - // update arithmetic flag fields if required - if(mask & PSR_FLAGS) { - arm->aflags.ZF = PSR_FIELD(arm, Z); - arm->aflags.NF = PSR_FIELD(arm, N); - arm->aflags.CF = PSR_FIELD(arm, C); - arm->aflags.VF = PSR_FIELD(arm, V); - arm->oflags.QF = PSR_FIELD(arm, Q); - } - - // update if-then state if required - if(mask & PSR_IT) { - arm->itStateRT = (PSR_FIELD(arm, IT10) | (PSR_FIELD(arm, IT72<<2))); - } - - // update processor mode if required - if((oldHandlerMode!=newHandlerMode) || (oldCPSRT!=newCPSRT)) { - updateMode(arm); - } -} - -// -// Write PRIMASK register -// -void armWritePRIMASK(armP arm, Uns32 value) { - - value &= PRIMASK_MASK; - - if(arm->sregs.PRIMASK != value) { - arm->sregs.PRIMASK = value; - armRefreshExecutionPriority(arm); - } -} - -// -// Write BASEPRI register -// -void armWriteBASEPRI(armP arm, Uns32 value) { - - value &= (BASEPRI_MASK & arm->priorityMask); - - if(arm->sregs.BASEPRI != value) { - arm->sregs.BASEPRI = value; - armRefreshExecutionPriority(arm); - } -} - -// -// Write BASEPRI register (using BASEPRI_MAX semantics) -// -void armWriteBASEPRI_MAX(armP arm, Uns32 value) { - - value &= (BASEPRI_MASK & arm->priorityMask); - - if(value && ((valuesregs.BASEPRI) || !arm->sregs.BASEPRI)) { - arm->sregs.BASEPRI = value; - armRefreshExecutionPriority(arm); - } -} - -// -// Write FAULTMASK register -// -void armWriteFAULTMASK(armP arm, Uns32 value) { - - value &= FAULTMASK_MASK; - - if((arm->executionPriority>-1) && (value!=arm->sregs.FAULTMASK)) { - arm->sregs.FAULTMASK = value; - armRefreshExecutionPriority(arm); - } -} - -// -// update the CONTROL.FPCA bit to the value. If it changes then set the block mask -// -void armUpdateFPCA(armP arm, Bool value) { - - // if CONTROL.FPCA changes set new value and set the block mask - if (CONTROL_FIELD(arm, FPCA) != value) { - - CONTROL_FIELD(arm, FPCA) = value; - armSetBlockMask(arm); - - } -} - -// -// update the FPCCR.LSPACT bit to the value. If it changes then set the block mask -// -void armUpdateLSPACT(armP arm, Bool value) { - - // if FPCCR.LSPACT changes set new value and set the block mask - if (SCS_FIELD(arm, FPCCR, LSPACT) != value) { - - SCS_FIELD(arm, FPCCR, LSPACT) = value; - armSetBlockMask(arm); - - } -} - -// -// Write CONTROL register -// -void armWriteCONTROL(armP arm, Uns32 value) { - - armCONTROL u = {reg:value}; - - // update CONTROL.FPCA (FPCA is only implemented if FPU is present) - if (FPU_PRESENT(arm)) { - armUpdateFPCA(arm, u.fields.FPCA); - } - - // update CONTROL.threadUnpriv - Bool oldUserMode = IN_USER_MODE(arm); - CONTROL_FIELD(arm, threadUnpriv) = u.fields.threadUnpriv; - Bool newUserMode = IN_USER_MODE(arm); - - // handle any switch to user mode - if(oldUserMode!=newUserMode) { - updateMode(arm); - } - - // CONTROL.useSP_Process may only be modified in Thread mode - if(!IN_HANDLER_MODE(arm)) { - armWriteSPProcess(arm, u.fields.useSP_Process); - } -} - -// -// Write SP register -// -void armWriteSP(armP arm, Uns32 value) { - arm->regs[ARM_REG_SP] = value & ~3; -} - -// -// Switch processor mode if required -// -void armSwitchMode(armP arm) { - - armMode mode; - - if(!IN_THUMB_MODE(arm)) { - - // invalid mode - mode = ARM_MODE_ARM; - SCS_FIELD(arm, CFSR, INVSTATE) = 1; - - } else { - - mode = 0; - - // user/kernel mode mask - if(IN_USER_MODE(arm)) { - mode |= ARM_MODE_U; - } - - // add MPU enable mask - if(!MPU_ENABLED(arm)) { - // no action - } else if(arm->executionPriority>=0) { - mode |= ARM_MODE_MPU; - } else if(SCS_FIELD(arm, MPU_CONTROL, HFNMIENA)) { - mode |= ARM_MODE_MPU; - } - } - - // switch mode if required - if(mode != arm->mode) { - vmirtSetMode((vmiProcessorP)arm, mode); - arm->mode = mode; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// PROCESSOR RUN STATE TRANSITION HANDLING -//////////////////////////////////////////////////////////////////////////////// - -// -// If this memory access callback is triggered, abort any active load linked -// -static VMI_MEM_WATCH_FN(abortEA) { - armAbortExclusiveAccess((armP)userData); -} - -// -// Install or remove the exclusive access monitor callback -// -static void updateExclusiveAccessCallback(armP arm, Bool install) { - - memDomainP domain = vmirtGetProcessorDataDomain((vmiProcessorP)arm); - Uns32 simLow = arm->exclusiveTag; - Uns32 simHigh = simLow + ~arm->exclusiveTagMask; - - // install or remove a watchpoint on the current exclusive access address - if(install) { - vmirtAddWriteCallback(domain, simLow, simHigh, abortEA, arm); - } else { - vmirtRemoveWriteCallback(domain, simLow, simHigh, abortEA, arm); - } -} - -// -// Abort any active exclusive access -// -void armAbortExclusiveAccess(armP arm) { - - if(arm->exclusiveTag != ARM_NO_TAG) { - - // remove callback on exclusive access monitor region - updateExclusiveAccessCallback(arm, False); - - // clear exclusive tag (AFTER updateExclusiveAccessCallback) - arm->exclusiveTag = ARM_NO_TAG; - } -} - -// -// This is called on simulator context switch (when this processor is either -// about to start or about to stop simulation) -// -VMI_IASSWITCH_FN(armContextSwitchCB) { - - armP arm = (armP)processor; - - // establish a watchpoint on a pending exclusive address to detect if that - // address is written elsewhere. - if(arm->exclusiveTag != ARM_NO_TAG) { - updateExclusiveAccessCallback(arm, state==RS_SUSPEND); - } - - // if a processor is about to be run, make state consistent with any changes - // that may have occurred while the processor was suspended - if(state==RS_RUN) { - armSetBlockMask(arm); - } -} - diff --git a/simulators/ovp/armmModel/armmVFP.c b/simulators/ovp/armmModel/armmVFP.c deleted file mode 100644 index d0f6ea1e..00000000 --- a/simulators/ovp/armmModel/armmVFP.c +++ /dev/null @@ -1,876 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -// VMI header files -#include "vmi/vmiRt.h" -#include "vmi/vmiMessage.h" - -// model header files -#include "armFPConstants.h" -#include "armMessage.h" -#include "armVFP.h" -#include "armSysRegisters.h" -#include "armStructure.h" -#include "armUtils.h" - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARMM_VFP" - -// -// Return current program counter -// -inline static Uns32 getPC(armP arm) { - return vmirtGetPC((vmiProcessorP)arm); -} - - -//////////////////////////////////////////////////////////////////////////////// -// FLOATING POINT CONTROL PREDICATES -//////////////////////////////////////////////////////////////////////////////// - -// -// Return the current rounding control -// -static vmiFPRC getRoundingControl(armP arm) { - - // map ARM rounding mode to VMI rounding mode - static const vmiFPRC modeMap[] = { - [0] = vmi_FPR_NEAREST, - [1] = vmi_FPR_POS_INF, - [2] = vmi_FPR_NEG_INF, - [3] = vmi_FPR_ZERO - }; - - if(SCS_USE_CPUID(arm) && !SCS_FIELD(arm, MVFR0, VFP_RoundingModes)) { - // if rounding modes are not supported, use vmi_FPR_NEAREST - return vmi_FPR_NEAREST; - } else { - // return the mapped rounding mode - return modeMap[FPSCR_FIELD(arm, RMode)]; - } -} - -// -// Should the default NaN be returned in any calculation that produces a NaN? -// -inline static Bool returnDefaultNaN(armP arm) { - return ( - // in VFP mode, return the default NaN if FPSCR.DN is set - FPSCR_FIELD(arm, DN) || - // MVFR1.DefaultNaNMode=0 indicates hardware supports only the default - // NaN mode - (SCS_USE_CPUID(arm) && !SCS_FIELD(arm, MVFR1, DefaultNaNMode)) - ); -} - -// -// Is flush-to-zero mode enabled? -// -inline static Bool inFTZMode(armP arm) { - return ( - // flush-to-zero is enabled if FPSCR.FZ is set - FPSCR_FIELD(arm, FZ) || - // MVFR1.FlushToZeroMode=0 indicates hardware supports only - // flush-to-zero mode - (SCS_USE_CPUID(arm) && !SCS_FIELD(arm, MVFR1, FlushToZeroMode)) - ); -} - -// -// Is alternative half precision mode enabled? -// -inline static Bool inAHPMode(armP arm) { - return FPSCR_FIELD(arm, AHP); -} - -//////////////////////////////////////////////////////////////////////////////// -// FLOATING REGISTER ACCESS -//////////////////////////////////////////////////////////////////////////////// - -// -// Set control word -// -inline static void setControlWord(armP arm, armFPCW new) { - if(arm->currentCW.u32 != new.u32) { - arm->currentCW = new; - vmirtSetFPControlWord((vmiProcessorP)arm, new.cw); - } -} - -// -// Update VFP control word to make it consistent with the FPSCR -// -static void updateVFPControlWord(armP arm) { - - // Mask off all exceptions */ - armFPCW newFPCW = {.cw.IM=1, .cw.DM=1, .cw.ZM=1, .cw.OM=1, .cw.UM=1, .cw.PM=1}; - - // set rounding control, denormals-are-zero and flush-to-zero - newFPCW.cw.RC = getRoundingControl(arm); - newFPCW.cw.DAZ = newFPCW.cw.FZ = inFTZMode(arm); - - // Set the new control word - setControlWord(arm, newFPCW); - -} - -// -// Write VFP FPSCR register -// -void armWriteFPSCR(armP arm, Uns32 newValue, Uns32 writeMask) { - - Uns32 oldValue = FPSCR_REG(arm); - - // update raw register - FPSCR_REG(arm) = ((oldValue & ~writeMask) | (newValue & writeMask)); - - // set denormal input sticky flag - arm->denormalInput = FPSCR_FIELD(arm, IDC); - - // set sticky flags - vmiFPFlags sticky = {0}; - sticky.f.I = FPSCR_FIELD(arm, IOC); // invalid operation flag - sticky.f.Z = FPSCR_FIELD(arm, DZC); // divide-by-zero flag - sticky.f.O = FPSCR_FIELD(arm, OFC); // overflow flag - sticky.f.U = FPSCR_FIELD(arm, UFC); // underflow flag - sticky.f.P = FPSCR_FIELD(arm, IXC); // inexact flag - arm->sdfpSticky = sticky.bits; - - // set comparison flags - arm->sdfpAFlags.NF = (FPSCR_FIELD(arm, N)) ? 1 : 0; - arm->sdfpAFlags.ZF = (FPSCR_FIELD(arm, Z)) ? 1 : 0; - arm->sdfpAFlags.CF = (FPSCR_FIELD(arm, C)) ? 1 : 0; - arm->sdfpAFlags.VF = (FPSCR_FIELD(arm, V)) ? 1 : 0; - - // update simulator floating point control word - updateVFPControlWord(arm); - -} - -// -// Read VFP FPSCR register -// -Uns32 armReadFPSCR(armP arm) { - - // compose denormal input flag - FPSCR_FIELD(arm, IDC) = arm->denormalInput; - - // compose remaining sticky flags - vmiFPFlags sticky = {arm->sdfpSticky}; - FPSCR_FIELD(arm, IOC) = sticky.f.I; // invalid operation flag - FPSCR_FIELD(arm, DZC) = sticky.f.Z; // divide-by-zero flag - FPSCR_FIELD(arm, OFC) = sticky.f.O; // overflow flag - FPSCR_FIELD(arm, UFC) = sticky.f.U; // underflow flag - FPSCR_FIELD(arm, IXC) = sticky.f.P; // inexact flag - - // compose comparison flags - FPSCR_FIELD(arm, N) = (arm->sdfpAFlags.NF) ? 1 : 0; - FPSCR_FIELD(arm, Z) = (arm->sdfpAFlags.ZF) ? 1 : 0; - FPSCR_FIELD(arm, C) = (arm->sdfpAFlags.CF) ? 1 : 0; - FPSCR_FIELD(arm, V) = (arm->sdfpAFlags.VF) ? 1 : 0; - - // return composed value - return FPSCR_REG(arm); -} - -//////////////////////////////////////////////////////////////////////////////// -// EXCEPTION FLAG UTILITIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Validate that an exception is disabled -// -inline static void validateFTZ(armP arm) { - VMI_ASSERT( - inFTZMode(arm), - "expected enabled flush-to-zero mode" - ); -} - -// -// Set the denormal sticky bit (when flush-to-zero mode is enabled) -// -static void setDenormalStickyFTZ(armP arm) { - validateFTZ(arm); - arm->denormalInput = 1; -} - -// -// Set the underflow sticky bit (when flush-to-zero mode is enabled) -// -static void setUnderflowStickyFTZ(armP arm) { - validateFTZ(arm); - const static vmiFPFlags underflow = {f:{U:1}}; - arm->sdfpSticky |= underflow.bits; -} - -// -// Raise the denormal exception -// -static void raiseDenormal(armP arm) { - arm->denormalInput = 1; -} - -// -// Raise the underflow exception -// -static void raiseUnderflow(armP arm) { - const static vmiFPFlags underflow = {f:{U:1}}; - arm->sdfpSticky |= underflow.bits; -} - -// -// Raise the overflow exception -// -static void raiseOverflow(armP arm) { - const static vmiFPFlags overflow = {f:{O:1}}; - arm->sdfpSticky |= overflow.bits; -} - -// -// Raise the invalid operation exception -// -static void raiseInvalidOperation(armP arm) { - const static vmiFPFlags invalidOperation = {f:{I:1}}; - arm->sdfpSticky |= invalidOperation.bits; -} - -// -// Raise the inexact exception -// -static void raiseInexact(armP arm) { - const static vmiFPFlags inexact = {f:{P:1}}; - arm->sdfpSticky |= inexact.bits; -} - - -//////////////////////////////////////////////////////////////////////////////// -// HALF-PRECISION OPERATIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// Convert from half-precision to single-precision -// -Uns32 armFPHalfToSingle(armP arm, Uns16 half) { - - Int32 exponent = ARM_FP16_EXPONENT(half); - Uns32 fraction = ARM_FP16_FRACTION(half); - Bool sign = ARM_FP16_SIGN(half); - Bool expAll1 = (exponent==ARM_FP16_EXP_ONES); - Bool isZero = (!exponent && !fraction); - Bool isInfinity = (expAll1 && !fraction); - Bool isNaN = (expAll1 && !isInfinity); - Bool useAHP = inAHPMode(arm); - - if(isInfinity && !useAHP) { - - // infinities require exponent correction - exponent = ARM_FP32_EXPONENT(ARM_FP32_PLUS_INFINITY); - fraction = ARM_FP32_FRACTION(ARM_FP32_PLUS_INFINITY); - - } else if(isZero) { - - // zero values require no special processing - - } else if(isNaN && !useAHP) { - - // argument is an SNaN if MSB of fraction is clear - Bool isSNaN = !(fraction & (1 << (ARM_FP16_EXP_SHIFT-1))); - - // raise Invalid Operation exception if an SNaN - if(isSNaN) { - raiseInvalidOperation(arm); - } - - if(returnDefaultNaN(arm)) { - - // default QNaN is required - exponent = ARM_FP32_EXPONENT(ARM_QNAN_DEFAULT_32); - fraction = ARM_FP32_FRACTION(ARM_QNAN_DEFAULT_32); - sign = ARM_FP32_SIGN(ARM_QNAN_DEFAULT_32); - - } else { - - // NaNs require exponent correction - exponent = ARM_FP32_EXP_ONES; - - // NaNs require fraction correction - fraction = fraction << (ARM_FP32_EXP_SHIFT - ARM_FP16_EXP_SHIFT); - fraction |= ARM_QNAN_MASK_32; - } - - } else { - - // normalize a denormal value if required - if(!exponent) { - - // shift up until implicit MSB is 1 - do { - fraction <<= 1; - exponent--; - } while(!(fraction & (1<> (ARM_FP32_EXP_SHIFT - ARM_FP16_EXP_SHIFT); - fraction |= ARM_QNAN_MASK_16; - } - - } else if(isDenormal && inFTZMode(arm)) { - - // flush denormals to zero if required - setDenormalStickyFTZ(arm); - exponent = 0; - fraction = 0; - - } else { - - // split value into sign, unrounded mantissa and exponent - union {Uns32 u32; Flt32 f32;} u = {single}; - Flt32 result = u.f32; - Flt32 mantissa = sign ? -result : result; - exponent = 0; - while(mantissa<1.0) { - mantissa *= 2.0; exponent--; - } - while(mantissa>=2.0) { - mantissa /= 2.0; exponent++; - } - - // bias the exponent so that the minimum exponent becomes 1, lower - // values 0 (indicating possible underflow) - exponent -= ARM_FP16_EXP_MIN; - while(exponent<0) { - exponent++; - mantissa /= 2.0; - } - - // get the unrounded mantissa as an integer and the "units in last - // place" rounding error - Flt32 mantissaExp2F = mantissa*(1<0.5) || ((error==0.5) && (fraction&1))); - overflowToInf = True; - break; - - case vmi_FPR_POS_INF: - roundUp = (error && !sign); - overflowToInf = !sign; - break; - - case vmi_FPR_NEG_INF: - roundUp = (error && sign); - overflowToInf = sign; - break; - - default: - roundUp = False; - overflowToInf = False; - break; - } - - if(roundUp) { - - fraction++; - - // check for round up from denormalized to normalized - if(fraction==(1<=((1<=(1<isFlt32 && (arg->u32 & ARM_QNAN_MASK_32); -} - -// -// Is the argument a 64-bit QNaN? -// -inline static Bool is64BitQNaN(vmiFPNaNArgP arg) { - return !arg->isFlt32 && (arg->u64 & ARM_QNAN_MASK_64); -} - -// -// Is the argument a 32-bit SNaN? -// -inline static Bool is32BitSNaN(vmiFPNaNArgP arg) { - return arg->isFlt32 && !(arg->u32 & ARM_QNAN_MASK_32); -} - -// -// Is the argument a 64-bit SNaN? -// -inline static Bool is64BitSNaN(vmiFPNaNArgP arg) { - return !arg->isFlt32 && !(arg->u64 & ARM_QNAN_MASK_64); -} - -// -// Handle 32-bit QNaN result -// -static VMI_FP_QNAN32_RESULT_FN(handleQNaN32) { - - armP arm = (armP)processor; - - if(!NaNArgNum || returnDefaultNaN(arm)) { - - return ARM_QNAN_DEFAULT_32; - - } else { - - Uns32 i; - - // PASS 1: if any argument is an 32-bit SNaN, return that (as a QNaN) - for(i=0; icurrentCW.u32 = -1; - - // Initialize FP registers if present (AFTER armSysInitialize) - if (SCS_USE_CPUID(arm) && FPU_PRESENT(arm)) { - - // initialize constant tiny values - initTinyValues(); - - // set up QNaN values and handlers - vmirtConfigureFPU( - (vmiProcessorP)arm, - ARM_QNAN_DEFAULT_32, - ARM_QNAN_DEFAULT_64, - 0, // indeterminate value not used - 0, // indeterminate value not used - 0, // indeterminate value not used - handleQNaN32, - handleQNaN64, - handleIndeterminate16, - handleIndeterminate32, - 0, // 64-bit indeterminate value handler not required - handleTinyResult, - handleTinyArgument, - True - ); - - // Set the write mask for CPACR to allow updating field cp10 and cp11 - SCS_MASK_FIELD(arm, CPACR, cp10) = 3; - SCS_MASK_FIELD(arm, CPACR, cp11) = 3; - - } -} - -// -// Call on reset -// -void armFPReset(armP arm) { - - // no action unless floating point is implemented - if(SCS_USE_CPUID(arm) && FPU_PRESENT(arm)) { - armWriteFPSCR(arm, 0, FPSCR_MASK); - } -} - - - diff --git a/simulators/ovp/armmModel/armmVM.c b/simulators/ovp/armmModel/armmVM.c deleted file mode 100644 index 47784862..00000000 --- a/simulators/ovp/armmModel/armmVM.c +++ /dev/null @@ -1,1271 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL - * UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS - * TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER - * IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD - * PARTY PATENTS. - * - * THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR - * MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING - * A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE - * FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER. - * YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW - * PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED - * AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE, - * MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM. - * - * Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include // for sprintf - -// Imperas header files -#include "hostapi/impAlloc.h" - -// VMI header files -#include "vmi/vmiAttrs.h" -#include "vmi/vmiMessage.h" -#include "vmi/vmiRt.h" -#include "vmi/vmiTypes.h" - -// model header files -#include "armExceptions.h" -#include "armFunctions.h" -#include "armStructure.h" -#include "armMessage.h" -#include "armSys.h" -#include "armVM.h" -#include "armUtils.h" - -// -// Prefix for messages from this module -// -#define CPU_PREFIX "ARM_VM" - -// -// This is the minimum region size usable with SRD bits and the number of -// subregions per region -// -#define SRD_MIN_SIZE 256 -#define SRD_REGIONS 8 - - -//////////////////////////////////////////////////////////////////////////////// -// UTILITIES -//////////////////////////////////////////////////////////////////////////////// - -// -// Return current program counter -// -inline static Uns32 getPC(armP arm) { - return vmirtGetPC((vmiProcessorP)arm); -} - -// -// Return instruction memory domain set for the passed processor -// -inline static armDomainSetP getDomainSetI(armP arm) { - return &arm->ids; -} - -// -// Return data memory domain set for the passed processor -// -inline static armDomainSetP getDomainSetD(armP arm) { - return &arm->dds; -} - -// -// Get the current code memDomain -// -inline static memDomainP getVirtualCodeDomain(armP arm) { - return vmirtGetProcessorCodeDomain((vmiProcessorP)arm); -} - -// -// Get the current data memDomain -// -inline static memDomainP getVirtualDataDomain(armP arm) { - return vmirtGetProcessorDataDomain((vmiProcessorP)arm); -} - -// -// Is code demain required for the passed privilege? -// -inline static Bool isFetch(memPriv priv) { - return priv==MEM_PRIV_X; -} - -// -// Return the memory domain set to use for the passed memory access type -// -static armDomainSetP getDomainSetPriv(armP arm, memPriv priv) { - return isFetch(priv) ? getDomainSetI(arm) : getDomainSetD(arm); -} - -// -// Return the virtual memory domain to use for the passed memory access type -// -static memDomainP getVirtualDomainPriv(armP arm, memPriv priv) { - return isFetch(priv) ? getVirtualCodeDomain(arm) : getVirtualDataDomain(arm); -} - -// -// Set the current data memDomain -// -inline static void setVirtualDataDomain(armP arm, memDomainP domain) { - vmirtSetProcessorDataDomain((vmiProcessorP)arm, domain); -} - -// -// Push to a new data memDomain, marking the processor to indicate restoration -// is required -// -inline static void pushVirtualDataDomain(armP arm, memDomainP domain) { - setVirtualDataDomain(arm, domain); - arm->restoreDomain = True; -} - -// -// Return the virtual data domain for the passed mode -// -static memDomainP getVirtualDataDomainMode(armP arm) { - armDomainSetP set = getDomainSetD(arm); - return IN_USER_MODE(arm) ? set->vmUser : set->vmPriv; -} - -// -// Restore correct virtual code domain for the processor, if required -// -static void restoreVirtualDataDomain(armP arm) { - setVirtualDataDomain(arm, getVirtualDataDomainMode(arm)); - arm->restoreDomain = False; -} - -// -// Given a raw privilege (AP format), return the effective privilege based on -// mode only for user mode MPU accesses -// -static memPriv getPrivMPUU(armP arm, Uns8 AP, Bool XN) { - - static const memPriv privMap[] = { - [0] = MEM_PRIV_NONE, - [1] = MEM_PRIV_NONE, - [2] = MEM_PRIV_RX, - [3] = MEM_PRIV_RWX, - [4] = MEM_PRIV_NONE, - [5] = MEM_PRIV_NONE, - [6] = MEM_PRIV_RX, - [7] = MEM_PRIV_NONE - }; - - memPriv result = (AP>7) ? MEM_PRIV_NONE : privMap[AP]; - - // apply XN bit if required - if(XN) {result &= ~MEM_PRIV_X;} - - return result; -} - -// -// Given a raw privilege (AP format), return the effective privilege based on -// mode only for privileged mode MPU accesses -// -static memPriv getPrivMPUP(armP arm, Uns8 AP, Bool XN) { - - static const memPriv privMap[] = { - [0] = MEM_PRIV_NONE, - [1] = MEM_PRIV_RWX, - [2] = MEM_PRIV_RWX, - [3] = MEM_PRIV_RWX, - [4] = MEM_PRIV_NONE, - [5] = MEM_PRIV_RX, - [6] = MEM_PRIV_RX, - [7] = MEM_PRIV_NONE - }; - - memPriv result = (AP>7) ? MEM_PRIV_NONE : privMap[AP]; - - // apply XN bit if required - if(XN) {result &= ~MEM_PRIV_X;} - - return result; -} - -// -// Given a raw privilege (AP format), return the effective privilege considering -// mode only (MPU accesses). A special case is that accesses in kernel mode -// where the current data memDomain is actually the user mode memDomain should -// be treated as user mode accesses (LDRT, STRT). -// -static memPriv getPrivMPU(armP arm, Uns8 AP, Bool XN) { - - if(IN_USER_MODE(arm)) { - // normal user-mode case - return getPrivMPUU(arm, AP, XN); - } else if(getVirtualDataDomain(arm)==getDomainSetD(arm)->vmUser) { - // special case for LDRT and STRT accesses - return getPrivMPUU(arm, AP, XN); - } else { - // normal privileged-mode case - return getPrivMPUP(arm, AP, XN); - } -} - -// -// Return a domian mask (the largest valid address in a domain) -// -static Uns64 getDomainMask(memDomainP domain) { - - Uns8 bits = vmirtGetDomainAddressBits(domain); - - return (bits==64) ? -1ULL : ((1ULL<external, domainV, lowPA, highPA, lowVA, 0, priv, G, ASID - ); -} - -// -// Do required actions when an invalid memory access occurs, either a processor -// access or a DMA unit access -// -static void handleInvalidAccess( - armP arm, - Uns32 MVA, - memPriv requiredPriv, - memAccessAttrs attrs -) { - if(!attrs) { - // no action for artifact access - } else { - // processor-generated exception - armMemoryAbort(arm, MVA, requiredPriv); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// MPU FUNCTIONS -//////////////////////////////////////////////////////////////////////////////// - -typedef enum protRegionCodeE { - PEC_ENABLED, // enabled area description - PEC_DISABLED, // disabled area description - PEC_INVALID_SIZE, // invalid size (less than minumum) - PEC_INVALID_BASE, // invalid base (not a multiple of size) -} protRegionCode; - -// this type represents a single protection area entry -typedef struct protRegionS { - Uns32 Base; // entry base address - Uns32 SRD : 8; // subrange disable - Uns32 Size : 5; // area size - Uns32 TEX : 3; // TEX field (ARMv6 and later) - Uns32 AP : 3; // area permissions - Bool E : 1; // enabled? - Bool XN : 1; // XN bit (ARMv6 and later) - Bool S : 1; // S bit (ARMv6 and later) - Bool C : 1; // C bit (ARMv6 and later) - Bool B : 1; // B bit (ARMv6 and later) -} protRegion; - -// pointer to a constant protRegion -typedef const struct protRegionS *protRegionCP; - -// -// Return description string identifying MPU -// -static const char *getMPUName(armP arm, Bool isData) { - return MPU_UNIFIED(arm) ? "" : isData ? " (D)" : " (I)"; -} - -// -// Return the count of the number of protection regions -// -static Uns32 mpuRegionNum(armP arm, Bool isData) { - if(isData || MPU_UNIFIED(arm)) { - return SCS_FIELD(arm, MPU_TYPE, DREGION); - } else { - return SCS_FIELD(arm, MPU_TYPE, DREGION); - } -} - -// -// Validate that the passed index is a valid MPU region index -// -static Bool validateRegionNum(armP arm, Bool isData, Uns32 index) { - - Uns32 regionNum = mpuRegionNum(arm, isData); - - if(index >= regionNum) { - - vmiMessage("a", CPU_PREFIX"_ROOR", - SRCREF_FMT "protection area index %u exceeds maximum (%u)", - SRCREF_ARGS(arm, getPC(arm)), - index, regionNum-1 - ); - - return False; - - } else { - - return True; - } -} - -// -// Return a pointer to the Protection Area Control registers -// -inline static protRegionP getPACRegs(armP arm, Bool isData) { - return (isData && arm->dmpu) ? arm->dmpu : arm->impu; -} - -// -// If the passed protection entry describes a valid region, set the bounds of -// that region and return PEC_ENABLED; otherwise return an enum member giving -// the reason why it is not valid -// -static protRegionCode getProtectionEntryRange( - armP arm, - protRegionCP pa, - Uns32 *lowP, - Uns32 *highP -) { - if(!pa->E) { - - // disabled region - return PEC_DISABLED; - - } else { - - // minimum region size allowed depends on MPU revision - Uns32 minSize = 4; - Uns32 minDelta = (2 << minSize) - 1; - - // get the region size (minus 1) - Uns32 size = pa->Size; - Uns32 delta = (2 << size) - 1; - - // are some subranges enabled? - Uns32 SRE = ~pa->SRD; - - if(!SRE && (delta>=(SRD_MIN_SIZE-1))) { - - // all subranges disabled - return PEC_DISABLED; - - } else { - - // get the region base address - Uns32 low = pa->Base; - - // return implied bounds - *lowP = low; - *highP = low + delta; - - if(deltaids.vmPriv, arm->dds.vmPriv, low, high, isData); - - // remove user domain access permissions - removePrivMPU(arm, arm->ids.vmUser, arm->dds.vmUser, low, high, isData); -} - -// -// If the indexed protection entry is valid, unmap it -// -static void unmapProtectionEntry(armP arm, Uns32 low, Uns32 high, Bool isData) { - - // remove main mappings - unmapProtectionEntryInt(arm, low, high, isData); -} - -// -// Update MPU status when an MPU region entry has been updated -// -static void resetProtectionEntryRange( - armP arm, - Uns32 index, - Bool isData, - Bool verbose -) { - protRegionP pacRegs = getPACRegs(arm, isData); - protRegionP pacReg = pacRegs+index; - Uns32 low; - Uns32 high; - - // validate new protection area permissions - switch(getProtectionEntryRange(arm, pacReg, &low, &high)) { - - case PEC_ENABLED: - // remove any existing mapping for the new protection entry range - unmapProtectionEntry(arm, low, high, isData); - break; - - case PEC_INVALID_SIZE: - // size error assertion - if(verbose) { - vmiMessage("a", CPU_PREFIX"_PEIS", - SRCREF_FMT "protection area %u has invalid size (%u bytes)", - SRCREF_ARGS(arm, getPC(arm)), - index, high - low + 1 - ); - } - break; - - case PEC_INVALID_BASE: - // base error assertion - if(verbose) { - vmiMessage("a", CPU_PREFIX"_PEIB", - SRCREF_FMT "protection area %u base 0x%08x is not a " - "multiple of size", - SRCREF_ARGS(arm, getPC(arm)), - index, low - ); - } - break; - - default: - // disabled entry - break; - } -} - -// -// Update the indexed region Base, SRD, Size or E fields -// -static void updateRegionBaseSRDSizeE( - armP arm, - Uns32 index, - Bool isData, - Uns32 Base, - Uns32 SRD, - Uns32 Size, - Uns32 E -) { - protRegionP pacRegs = getPACRegs(arm, isData); - protRegionP pacReg = pacRegs+index; - - // action is required only if the register changes value - if( - (pacReg->Base!=Base) || - (pacReg->SRD!=SRD) || - (pacReg->Size!=Size) || - (pacReg->E!=E) - ) { - // remove any current mapping for the protection entry - resetProtectionEntryRange(arm, index, isData, False); - - // update the entry - pacReg->Base = Base; - pacReg->SRD = SRD; - pacReg->Size = Size; - pacReg->E = E; - - // remove any mapping for the new region location - resetProtectionEntryRange(arm, index, isData, True); - } -} - -// -// Modify AP or XN fields for the indexed MPU region -// -static void updateRegionAPXN( - armP arm, - Uns32 index, - Bool isData, - Uns8 newAP, - Bool newXN -) { - protRegionP pacRegs = getPACRegs(arm, isData); - protRegionP pacReg = pacRegs+index; - Uns8 oldAP = pacReg->AP; - Uns8 oldXN = pacReg->XN; - - // update AP and XN fields - pacReg->AP = newAP; - pacReg->XN = newXN; - - // have region permissions on an enabled region changed? - if(pacReg->E && ((oldAP!=newAP) || (oldXN!=newXN))) { - - // get privileges implied by old and new permissions in each mode - memPriv oldPrivU = getPrivMPUU(arm, oldAP, oldXN); - memPriv oldPrivP = getPrivMPUP(arm, oldAP, oldXN); - memPriv newPrivU = getPrivMPUU(arm, newAP, newXN); - memPriv newPrivP = getPrivMPUP(arm, newAP, newXN); - - // if privileges have been reduced, disable all access to the area of - // memory assocaited with the region - if((oldPrivU & ~newPrivU) || (oldPrivP & ~newPrivP)) { - resetProtectionEntryRange(arm, index, isData, False); - } - } -} - -// -// This specifies the regions in the default system address map -// -static const protRegion sysRegions[] = { - {.Base=0x00000000, .Size=0x1c, .AP=3, .TEX=0, .C=1, .B=0, .E=1, .S=1, .XN=0}, - {.Base=0x20000000, .Size=0x1c, .AP=3, .TEX=1, .C=1, .B=1, .E=1, .S=1, .XN=0}, - {.Base=0x40000000, .Size=0x1c, .AP=3, .TEX=0, .C=0, .B=1, .E=1, .S=1, .XN=1}, - {.Base=0x60000000, .Size=0x1c, .AP=3, .TEX=1, .C=1, .B=1, .E=1, .S=1, .XN=0}, - {.Base=0x80000000, .Size=0x1c, .AP=3, .TEX=0, .C=1, .B=0, .E=1, .S=1, .XN=0}, - {.Base=0xa0000000, .Size=0x1c, .AP=3, .TEX=0, .C=0, .B=1, .E=1, .S=1, .XN=1}, - {.Base=0xc0000000, .Size=0x1c, .AP=3, .TEX=2, .C=0, .B=0, .E=1, .S=1, .XN=1}, - {.Base=0xe0000000, .Size=0x1c, .AP=3, .TEX=2, .C=0, .B=0, .E=1, .S=1, .XN=1} -}; - -// -// Return a protRegion structure representing the implicit Private Peripheral -// Bus region -// -static protRegionCP getPPBRegion(void) { - - static const protRegion ppbRegion = { - .Base=PPB_LOW, .Size=0x13, .AP=3, .E=1, .XN=1 - }; - - return &ppbRegion; -} - -// -// If the MVA lies in the region range rlow:rhigh, set by-ref arguments 'low' -// and 'high' with that range; otherwise, exclude the range rlow:rhigh from the -// currennt range in low:high -// -static Bool matchRegion( - Uns32 MVA, - Uns32 rlow, - Uns32 rhigh, - Uns32 *low, - Uns32 *high -) { - if((rlow<=MVA) && (rhigh>=MVA)) { - - // match in this region - *low = rlow; - *high = rhigh; - - return True; - - } else if((rlow>MVA) && (rlow<*high)) { - - // remove part of region ABOVE matching address - *high = rlow-1; - - } else if((rhigh*low)) { - - // remove part of region BELOW matching address - *low = rhigh+1; - } - - return False; -} - -// -// Return a boolean indicating if the passed MVA lies in the protection entry -// and update by-ref arguments 'low' and 'high' with the largest bounds -// enclosing the address -// -static Bool selectProtectionEntry( - armP arm, - protRegionCP try, - Uns32 MVA, - Uns32 *low, - Uns32 *high -) { - Uns32 rlow, rhigh; - - if(getProtectionEntryRange(arm, try, &rlow, &rhigh)!=PEC_ENABLED) { - - // entry is not enabled - return False; - - } else if(try->SRD && ((rhigh-rlow)>=(SRD_MIN_SIZE-1))) { - - // possible match in a subregion - Uns8 SRE = ~try->SRD; - Uns32 delta = ((Uns64)rhigh-rlow+1)/SRD_REGIONS; - Uns32 i; - - // iterate over all enabled subregions - for(i=0; SRE; i++, SRE>>=1) { - - // is this subregion enabled? - if(SRE & 1) { - - // derive subregion bounds - Uns32 srlow = rlow+(delta*i); - Uns32 srhigh = srlow+delta-1; - - // return if subregion matches - if(matchRegion(MVA, srlow, srhigh, low, high)) { - return True; - } - } - } - - // no subregion matches - return False; - - } else { - - // possible match in an entire region - return matchRegion(MVA, rlow, rhigh, low, high); - } -} - -// -// Try mapping memory at the passed address for the specified access type and -// return a Boolean indicating whether the mapping succeeded -// -static Bool mpuMiss( - armP arm, - memPriv requiredPriv, - Uns32 address, - Uns32 *lowVAP, - Uns32 *highVAP -) { - Uns32 MVA = address; - Bool isData = !(requiredPriv & MEM_PRIV_X); - protRegionP pacRegs = getPACRegs(arm, isData); - protRegionCP ppb = getPPBRegion(); - protRegionCP match = 0; - Uns32 regionNum = mpuRegionNum(arm, isData); - Uns32 low = 0; - Uns32 high = 0; - Uns32 i; - - // use the system address map as a background region in privileged mode if - // MPU_CONTROL.PRIVDEFENA is specified - if(!IN_USER_MODE(arm) && SCS_FIELD(arm, MPU_CONTROL, PRIVDEFENA)) { - match = sysRegions+(MVA/0x20000000); - selectProtectionEntry(arm, match, MVA, &low, &high); - } - - // scan regions in lowest-to-highest priority order - for(i=0; iAP; - Bool XN = match->XN; - memPriv priv = getPrivMPU(arm, AP, XN); - Uns32 lowVA = low; - Uns32 highVA = high; - - // if debug mode is enabled, report the range being mapped - if(ARM_DEBUG_MMU(arm)) { - vmiPrintf( - "MPU%s MAP VA 0x%08x:0x%08x PA 0x%08x:0x%08x AP %u%s\n", - getMPUName(arm, isData), - lowVA, highVA, - low, high, - AP, - XN ? "-x" : "" - ); - } - - // does the entry have sufficient permissions? - if((priv & requiredPriv) == requiredPriv) { - - // map MPU entry memory - mapDomainPairRange( - arm, requiredPriv, priv, low, high, lowVA, True, 0 - ); - - // MPU entry permissions are ok, but access may still not be - // possible if no physical memory exists at the physical address - memDomainP domainV = getVirtualDomainPriv(arm, requiredPriv); - memPriv actualPriv = vmirtGetDomainPrivileges(domainV, address); - - // indicate the address range that has been mapped - *lowVAP = lowVA; - *highVAP = highVA; - - return (actualPriv & requiredPriv) && True; - } - } - - // invalid access, either because no matching entry found or existing entry - // has insufficient permissions - return False; -} - -// -// Free an MPU data structure -// -static void freeMPU(protRegionP *mpuHandle) { - - protRegionP mpu = *mpuHandle; - - STYPE_FREE(mpu); - - *mpuHandle = 0; -} - -// -// Free an MPU data structure -// -static protRegionP newMPU(armP arm, Bool isData) { - - Uns32 regionNum = mpuRegionNum(arm, isData); - - return regionNum ? STYPE_CALLOC_N(protRegion, regionNum) : 0; -} - -// -// Reset an MPU data structure -// -static void resetMPU(armP arm, Bool isData) { - - Uns32 regionNum = mpuRegionNum(arm, isData); - Uns32 i; - - for(i=0; iimpu) { - freeMPU(&arm->impu); - } - - // free data MPU if required - if(arm->dmpu) { - freeMPU(&arm->dmpu); - } -} - -// -// Allocate MPU structures for the passed processor -// -static void newMPUs(armP arm) { - - // create instruction/unified MPU - arm->impu = newMPU(arm, False); - - // create data MPU if required - if(!MPU_UNIFIED(arm)) { - arm->dmpu = newMPU(arm, True); - } -} - -// -// Reset MPU contents -// -static void resetMPUs(armP arm) { - - // reset instruction/unified MPU - if(arm->impu) { - resetMPU(arm, False); - } - - // reset data MPU if required - if(arm->dmpu) { - resetMPU(arm, True); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// BIT-BAND REGIONS -//////////////////////////////////////////////////////////////////////////////// - -// -// This is the size of a bit-band region -// -#define BIT_BAND_SIZE 0x100000 - -// -// This is the offset to the alias region from the bit-band base -// -#define ALIAS_OFFSET 0x2000000 - -// -// Callback function to read a system register -// -static VMI_MEM_READ_FN(readBitBand) { - - if(processor) { - - armP arm = (armP)processor; - memDomainP domain = arm->dds.external; - UnsPS regionLow = (UnsPS)userData; - Uns32 aliasLow = regionLow + ALIAS_OFFSET; - Uns32 regionAddr = regionLow + (address - aliasLow) / 32; - Uns32 bitOffset = ((address - aliasLow) % 32) / 4; - - // get byte alias value - Uns8 result = vmirtRead1ByteDomain(domain, regionAddr, MEM_AA_TRUE); - - // extract required bit - result = (result>>bitOffset) & 1; - - // update correct-size result value - if(bytes==1) { - *(Uns8*)value = result; - } else if(bytes==2) { - *(Uns16*)value = result; - } else if(bytes==4) { - *(Uns32*)value = result; - } else { - VMI_ABORT("unimplemented bit-band access size %u bytes", bytes); - } - } -} - -// -// Callback function to read a system register -// -static VMI_MEM_WRITE_FN(writeBitBand) { - - if(processor) { - - armP arm = (armP)processor; - memDomainP domain = arm->dds.external; - UnsPS regionLow = (UnsPS)userData; - Uns32 aliasLow = regionLow + ALIAS_OFFSET; - Uns32 regionAddr = regionLow + (address - aliasLow) / 32; - Uns32 bitOffset = ((address - aliasLow) % 32) / 4; - Uns8 mask = 1<mode&ARM_MODE_MPU) { - - Uns32 lastVA = address+bytes-1; - Uns32 highVA = address-1; - Uns32 lowVA = address; - - // iterate over all MPU ranges straddled by this access - do { - address = highVA+1; - ok = mpuMiss(arm, requiredPriv, address, &lowVA, &highVA); - } while(ok && ((lastVAhighVA))); - } - - // generate exception for the first faulting address - if(ok) { - return MA_OK; - } else { - handleInvalidAccess(arm, address, requiredPriv, attrs); - return MA_EXCEPTION; - } -} - -// -// Set the privileged mode data domain to the user domain (for LDRT, STRT) -// -void armVMSetUserPrivilegedModeDataDomain(armP arm) { - pushVirtualDataDomain(arm, getDomainSetD(arm)->vmUser); -} - -// -// Restore the normal data domain for the current mode -// -void armVMRestoreNormalDataDomain(armP arm) { - restoreVirtualDataDomain(arm); -} - -// -// Write the indexed MPU RBAR register value -// -void armVMWriteRBAR(armP arm, Uns32 index, Bool isData, Uns32 newValue) { - - if(validateRegionNum(arm, isData, index)) { - - protRegionP pacReg = getPACRegs(arm, isData) + index; - - // prepare Base, SRD, Size and E arguments - Uns32 Base = newValue & SCS_MASK_MPU_RBAR_ADDR; - Uns32 SRD = pacReg->SRD; - Uns32 Size = pacReg->Size; - Uns32 E = pacReg->E; - - // update the required register - updateRegionBaseSRDSizeE(arm, index, isData, Base, SRD, Size, E); - } -} - -// -// Read the indexed MPU RBAR register value -// -Uns32 armVMReadRBAR(armP arm, Uns32 index, Bool isData) { - - if(validateRegionNum(arm, isData, index)) { - - protRegionP pacReg = getPACRegs(arm, isData) + index; - - // create mask to select Base field - union {SCS_REG_DECL(MPU_RBAR); Uns32 u32;} uMask = {{ADDR:-1}}; - - // return masked result - return pacReg->Base & uMask.u32; - - } else { - - return 0; - } -} - -// -// Write the indexed MPU RASR register value -// -void armVMWriteRASR(armP arm, Uns32 index, Bool isData, Uns32 newValue) { - - if(validateRegionNum(arm, isData, index)) { - - protRegionP pacReg = getPACRegs(arm, isData) + index; - - // create union to enable field extraction - union {Uns32 u32; SCS_REG_DECL(MPU_RASR);} u = {newValue}; - - // update fields with no simulation effect - pacReg->B = u.MPU_RASR.B; - pacReg->C = u.MPU_RASR.C; - pacReg->S = u.MPU_RASR.S; - pacReg->TEX = u.MPU_RASR.TEX; - - // prepare Base, SRD, Size, E, AP and XN arguments - Uns32 Base = pacReg->Base; - Uns32 SRD = u.MPU_RASR.SRD; - Uns32 Size = u.MPU_RASR.SIZE; - Uns32 E = u.MPU_RASR.ENABLE; - Uns8 AP = u.MPU_RASR.AP; - Bool XN = u.MPU_RASR.XN; - - // update the required register - updateRegionBaseSRDSizeE(arm, index, isData, Base, SRD, Size, E); - updateRegionAPXN(arm, index, isData, AP, XN); - } -} - -// -// Read the indexed MPU RASR register value -// -Uns32 armVMReadRASR(armP arm, Uns32 index, Bool isData) { - - if(validateRegionNum(arm, isData, index)) { - - protRegionP pacReg = getPACRegs(arm, isData) + index; - - // initialize result - union {Uns32 u32; SCS_REG_DECL(MPU_RASR);} u = {0}; - - // extract required fields - u.MPU_RASR.SRD = pacReg->SRD; - u.MPU_RASR.SIZE = pacReg->Size; - u.MPU_RASR.ENABLE = pacReg->E; - u.MPU_RASR.B = pacReg->B; - u.MPU_RASR.C = pacReg->C; - u.MPU_RASR.S = pacReg->S; - u.MPU_RASR.TEX = pacReg->TEX; - u.MPU_RASR.AP = pacReg->AP; - u.MPU_RASR.XN = pacReg->XN; - - // return composed result - return u.u32; - - } else { - - return 0; - } -} - -// -// Flush the privileged mode MPU -// -void armVMFlushMPUPriv(armP arm) { - - Bool isData = True; - - // if debug mode is enabled, report the range being unmapped - if(ARM_DEBUG_MMU(arm)) { - vmiPrintf("MPU%s FLUSH\n", getMPUName(arm, isData)); - } - - // remove privileged domain access permissions - removePrivMPU(arm, arm->ids.vmPriv, arm->dds.vmPriv, 0, -1, isData); -} - -// -// Virtual memory constructor -// -VMI_VMINIT_FN(armVMInit) { - - armP arm = (armP)processor; - Uns32 bits = ARM_GPR_BITS; - memDomainP extCodeDomain = codeDomains[0]; - memDomainP extDataDomain = dataDomains[0]; - memDomainP sysCodeDomain; - memDomainP sysDataDomain; - - // create system physical domains - if(extCodeDomain==extDataDomain) { - extCodeDomain = makeDomainAlias(extCodeDomain, "external"); - extDataDomain = extCodeDomain; - sysCodeDomain = makeDomainAlias(extCodeDomain, "system"); - sysDataDomain = sysCodeDomain; - } else { - extCodeDomain = makeDomainAlias(extCodeDomain, "external Code"); - extDataDomain = makeDomainAlias(extDataDomain, "external Data"); - sysCodeDomain = makeDomainAlias(extCodeDomain, "system Code"); - sysDataDomain = makeDomainAlias(extDataDomain, "system Data"); - } - - // add System Control Space register callbacks - armSysCreateSCSRegion(arm, extDataDomain); - - if (!arm->disableBitBand) { - // create bit-band regions - createBitBandRegion(extDataDomain, 0x20000000); - createBitBandRegion(extDataDomain, 0x40000000); - } - - // addresses in System Control Space are never executable - vmirtProtectMemory( - extCodeDomain, SYSTEM_LOW, SYSTEM_HIGH, MEM_PRIV_X, MEM_PRIV_SUB - ); - - // some addresses in the default system address map are also not executable - vmirtProtectMemory( - sysCodeDomain, PERIPH_LOW, PERIPH_HIGH, MEM_PRIV_X, MEM_PRIV_SUB - ); - vmirtProtectMemory( - sysCodeDomain, DEVICE_LOW, DEVICE_HIGH, MEM_PRIV_X, MEM_PRIV_SUB - ); - - // save physical memDomains on processor structure - arm->ids.external = extCodeDomain; - arm->ids.system = sysCodeDomain; - arm->dds.external = extDataDomain; - arm->dds.system = sysDataDomain; - - // set physical code memDomains for each mode - codeDomains[ARM_MODE_PRIV] = sysCodeDomain; - codeDomains[ARM_MODE_USER] = sysCodeDomain; - - // set physical data memDomains for each mode - dataDomains[ARM_MODE_PRIV] = sysDataDomain; - dataDomains[ARM_MODE_USER] = sysDataDomain; - - // initialize MPU data structures if required - if(MPU_PRESENT(arm)) { - - // create MPU-managed memDomains - arm->ids.vmPriv = vmirtNewDomain("priv MPU Code", bits); - arm->ids.vmUser = vmirtNewDomain("user MPU Code", bits); - arm->dds.vmPriv = vmirtNewDomain("priv MPU Data", bits); - arm->dds.vmUser = vmirtNewDomain("user MPU Data", bits); - - // set MPU code memDomains for each mode - codeDomains[ARM_MODE_PRIV_MPU] = arm->ids.vmPriv; - codeDomains[ARM_MODE_USER_MPU] = arm->ids.vmUser; - - // set MPU data memDomains for each mode - dataDomains[ARM_MODE_PRIV_MPU] = arm->dds.vmPriv; - dataDomains[ARM_MODE_USER_MPU] = arm->dds.vmUser; - - // initialize MPU if required - if(MPU_PRESENT(arm)) { - newMPUs(arm); - } - } -} - -// -// Reset VM structures -// -void armVMReset(armP arm) { - if(MPU_PRESENT(arm)) { - resetMPUs(arm); - } -} - -// -// Free structures used for virtual memory management -// -void armVMFree(armP arm) { - if(MPU_PRESENT(arm)) { - freeMPUs(arm); - } -} - - diff --git a/simulators/ovp/armmModel/export.def b/simulators/ovp/armmModel/export.def deleted file mode 100755 index 4b488d4a..00000000 --- a/simulators/ovp/armmModel/export.def +++ /dev/null @@ -1,3 +0,0 @@ -EXPORTS - vmiStubs - modelAttrs diff --git a/simulators/ovp/armmModel/failSALlink.cc b/simulators/ovp/armmModel/failSALlink.cc deleted file mode 100644 index cdc59403..00000000 --- a/simulators/ovp/armmModel/failSALlink.cc +++ /dev/null @@ -1,15 +0,0 @@ -#include -//#include "sal/SimulatorController.hpp" - -using namespace std; - - -void hello(unsigned int p){ - cout << "&fail::simulator: " << hex << p << endl; -// fail::SimulatorController * salp = reinterpret_cast(p); - -} - -extern "C" void failSALset(unsigned int pointer){ - hello(pointer); -} diff --git a/simulators/ovp/cortexM3/CMakeLists.txt b/simulators/ovp/cortexM3/CMakeLists.txt deleted file mode 100644 index 76e17967..00000000 --- a/simulators/ovp/cortexM3/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -add_definitions(" -m32 ${IMPERAS_VMIINC} ") - -set(SRCS - $ENV{IMPERAS_HOME}/ImpPublic/source/host/icm/icmCpuManager.cpp - platform/platform.cc - ../OVPPlatform.cc -) - -add_executable(ovp_cortexM3 ${SRCS}) -add_dependencies(ovp_cortexM3 fail-ovpstatusmessages ) - - -target_link_libraries(ovp_cortexM3 ${SIM_LDFLAGS} fail fail-ovpstatusmessages) -## OVP links all needed shared libraries via a runtimeloader -set_target_properties(ovp_cortexM3 PROPERTIES LINK_FLAGS "-L${CMAKE_BINARY_DIR}/lib -lpcl -lprotobuf -m32 ") diff --git a/simulators/ovp/cortexM3/platform/platform.cc b/simulators/ovp/cortexM3/platform/platform.cc deleted file mode 100644 index ac05e7aa..00000000 --- a/simulators/ovp/cortexM3/platform/platform.cc +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include - -#include "platform.hpp" -#include "statreg.hpp" -#include "sal/SALInst.hpp" - -#include "icm/icmCpuManager.h" -#include "icm/icmQuery.h" - -// enable relaxed scheduling for maximum performance -//#define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED|ICM_ATTR_TRACE) -#define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED) - -// GDB port -#define GDB_PORT 1234 - -// Variables set by arguments -const char *variant = "Cortex-M3"; // the model variant - -using namespace std; - -ARM_Cortex_M3 arm; - -ARM_Cortex_M3::ARM_Cortex_M3() { -} - -ARM_Cortex_M3::~ARM_Cortex_M3() { - delete platform; - delete cpu; - delete attrList; -} - -void ARM_Cortex_M3::init(bool gdb=false) { - - // initialize OVPsim, enabling verbose mode to get statistics at end of execution - platform = new icmPlatform("CortexM3Platform", //name - ICM_VERBOSE|ICM_STOP_ON_CTRLC, //attributes - gdb ? "rsp" : 0, // optional protocol - gdb ? GDB_PORT : 0); // optional port number - - -// const char *armModel = icmGetVlnvString(NULL, "arm.ovpworld.org", "processor", "armm", "1.0", "model"); - const char *armModel = "/srv/scratch/hoffmann/test/build/lib/libarmmModel.so"; - const char *armSemihost = icmGetVlnvString(NULL, "arm.ovpworld.org", "semihosting", "armNewlib", "1.0", "model"); - - attrList = new icmAttrListObject(); - - attrList->addAttr("endian", "little"); - attrList->addAttr("compatibility", "nopBKPT"); - attrList->addAttr("variant", variant); - attrList->addAttr("UAL", "1"); - attrList->addAttr("fail_salp", &fail::simulator); - - char cpuname[64]; - sprintf(cpuname,"cpu-%s", variant); - - // create a processor instance - cpu = new icmProcessorObject( - cpuname, // CPU name - "armm", // CPU type - 0, // CPU cpuId - 0, // CPU model flags - 32, // address bits - armModel, // model file - "modelAttrs", // morpher attributes - SIM_ATTRS, // attributes - attrList, // user-defined attributes - armSemihost, // semi-hosting file - "modelAttrs" // semi-hosting attributes - ); - - // Nominate this processor to be attached to a debugger - if(gdb) cpu->debugThisProcessor(); - - processorP = cpu->getProcessorP(); -} - -void ARM_Cortex_M3::createFullMMC(const char *vlnRoot=0) { -// TODO: ELF Groesse auslesen per OVP (hat funktionen) und dann den Bereich als MMC einrichten... -/* const char *mmc_model = icmGetVlnvString("/srv/scratch/sirozipp/build/lib", "ovpworld.org", "mmc", "failMMC", "1.0", "model"); - if(mmc_model == NULL) { - std::cerr << "mmc_model not found!" << std::endl; - exit(1); - } -*/ - const char *mmc_model = "/srv/scratch/sirozipp/build/lib/libflaky.so"; - - // create full MMCs - mmcInstr = new icmMmcObject("mmci", mmc_model, "modelAttrs", 0, False); - mmcData = new icmMmcObject("mmcd", mmc_model, "modelAttrs", 0, False); - - // create processor instruction and data bus - instrBus = new icmBusObject("instrbus", 32); - dataBus = new icmBusObject("databus", 32); - - // create processor main bus - mainBus = new icmBusObject("mainbus", 32); - - // connect processor ports to their buses - cpu->connect(*instrBus, *dataBus); - - // connect mmcs to buses - mmcInstr->connect(*instrBus, "sp1", False); - mmcData->connect(*dataBus, "sp1", False); - - // connet master ports of mmc to main bus - mmcInstr->connect(*mainBus, "mp1", True); - mmcData->connect(*mainBus, "mp1", True); - - // create simulated memory - Addr appHighAddr, appLowAddr; - - appHighAddr = 0xFFFFFFFF; - appLowAddr = 0x0; - icmMem0 = new icmMemoryObject("mem1", ICM_PRIV_RWX, appHighAddr-appLowAddr); - - // connect memory to main bus - icmMem0->connect("mp1", *mainBus, 0); -} - -static ICM_MEM_READ_FN(extMemRead) { - unsigned char res[4]; -// Int32 tmpres = *(Int32*)value; -// icmPrintf("EXTERNAL MEMORY: Reading 0x%08x from 0x%08x\n", *(Int32*)value, (Int32)address); -// *(Int32*) value = (Int32)arm.mem[(address-arm.offset)>>2]; - - fail::simulator.onMemoryAccessEvent(address, 4, false, ovpplatform.getPC()); - - res[0] = arm.mem[(address-arm.offset)+0]; - res[1] = arm.mem[(address-arm.offset)+1]; - res[2] = arm.mem[(address-arm.offset)+2]; - res[3] = arm.mem[(address-arm.offset)+3]; - -// icmPrintf("Reading [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", arm.mem[(address-arm.offset)+0], arm.mem[(address-arm.offset)+1], arm.mem[(address-arm.offset)+2], arm.mem[(address-arm.offset)+3]); - - *(Int32*)value = (res[3] << 24) | (res[2] << 16) | (res[1] << 8) | res[0]; -// -// icmPrintf("Reading: 0x%08x\n", (res[3] << 24) | (res[2] << 16) | (res[1] << 8) | res[0]); - -// icmPrintf("Callback: Reading 0x%08x from mem[0x%08x] should be 0x%08x from [0x%08x]\n", *(Int32*)value, (Int32)(address-arm.offset), tmpres, (Int32) address); - -} - -static ICM_MEM_WRITE_FN(extMemWrite) { -// icmPrintf("EXTERNAL MEMORY: Writing 0x%08x to 0x%08x\n", (Int32)value, (Int32)address); -// icmPrintf("Callback: Writing 0x%08x to mem[0x%08x] should be 0x%08x from [0x%08x]\n", *(Int32*)value, (Int32)(address-arm.offset), *(Int32*) value, (Int32) address); - fail::simulator.onMemoryAccessEvent(address, 4, true, ovpplatform.getPC()); - - Int32 val = *(Int32*)value; - - arm.mem[(address-arm.offset) + 0] = val & 0xFF; - arm.mem[(address-arm.offset) + 1] = (val >> 8) & 0xFF; - arm.mem[(address-arm.offset) + 2] = (val >> 16) & 0xFF; - arm.mem[(address-arm.offset) + 3] = (val >> 24) & 0xFF; - -// icmPrintf("Writing [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF, (val >> 24) & 0xFF); -// icmPrintf("Writing [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", arm.mem[(address-arm.offset)+0], arm.mem[(address-arm.offset)+1], arm.mem[(address-arm.offset)+2], arm.mem[(address-arm.offset)+3]); - -// Int32 res = arm.mem[(address-arm.offset)+0] | arm.mem[(address-arm.offset)+1] << 8 | arm.mem[(address-arm.offset)+2] << 16 | arm.mem[(address-arm.offset)+3] << 24; - -// icmPrintf("Callback: Writing 0x%08x to mem[0x%08x] should be 0x%08x to [0x%08x]\n", res, (Int32)(address-arm.offset), *(Int32*) value, (Int32) address); -// arm.mem[(address-arm.offset) >> 2] = *(Int32*) value; -} - -static ICM_MEM_READ_FN(extTextRead) { -// Int16 val = *(Int16*)value; - *(Int16*) value = (Int16)arm.textmem[(address-arm.textOffset)>>1]; -// icmPrintf("Callback: Reading 0x%04x from textmem[0x%08x] should be 0x%04x from [0x%08x]\n", *(Int16*)value, (Int32)(address-arm.textOffset), val, (Int32) address); -} - -static ICM_MEM_WRITE_FN(extTextWrite) { - arm.textmem[(address-arm.textOffset) >> 1] = *(Int16*) value; -} - -void ARM_Cortex_M3::mapMemToCallback() { - // create processor bus - mainBus = new icmBusObject("mainbus", 32); - - // connect the processor bus - cpu->connect(*mainBus, *mainBus); - - // create simulated memory - Addr appHighAddr, appLowAddr, textLowAddr, textHighAddr, LowAddr, LowAddrH, HighAddr, HighAddrL; - - appLowAddr = offset; - appHighAddr = appLowAddr + memSize - 1; - - textLowAddr = textOffset; - textHighAddr = textLowAddr + textMemSize - 1; - - // check which section is first - if(appLowAddr < textLowAddr) { - LowAddr = appLowAddr; - LowAddrH = appHighAddr; - HighAddr = textHighAddr; - HighAddrL = textLowAddr; - } else { - LowAddr = textLowAddr; - LowAddrH = textHighAddr; - HighAddr = appHighAddr; - HighAddrL = appLowAddr; - } - - // Memory from 0x0 to LowAddr - icmMem0 = new icmMemoryObject("mem0", ICM_PRIV_RWX, LowAddr - 1); - // Memory after callback mem to end - icmMem1 = new icmMemoryObject("mem1", ICM_PRIV_RWX, 0xFFFFFFFF - HighAddr - 1); - // Memory between text and other sections - icmMem2 = new icmMemoryObject("mem2", ICM_PRIV_RWX, HighAddrL - LowAddrH - 1 -1); - - // map the adress range appLowAddr:appHighAddr externally to the processor - mainBus->mapExternalMemory("external", ICM_PRIV_RWX, appLowAddr, appHighAddr, - extMemRead, // read callback - extMemWrite, // write callback - 0); - - mainBus->mapExternalMemory("exttext", ICM_PRIV_RWX, textLowAddr, textHighAddr, - extTextRead, - extTextWrite, - 0); - - // just build memory before external memory if it's not at the beginning - if(LowAddr > 0x0) { - icmMem0->connect("mp1", *mainBus, 0x0); - } - - if(HighAddr < 0xffffffff) { - icmMem1->connect("mp2", *mainBus, HighAddr+1); - } - - if(LowAddrH != HighAddrL) { - icmMem2->connect("mp3", *mainBus, LowAddrH+1); - } - - mainBus->printConnections(); -} - - -void ARM_Cortex_M3::makeGPRegister() { - const string names[] = {"r0", "r1", "r2", "r3", "r4", "r5", - "r6", "r7", "r8", "r9", "r10", "r11", "r12"}; - - - - for(int i = 0; i <= 12; ++i) { - icmRegInfoP reg = icmGetRegByIndex(processorP, i); - fail::simulator.makeGPRegister(32, (void *)reg, names[i]); - } - - // set SP pointer - // ARM Cortex M3: SP pointer is ID 13 - icmRegInfoP sp_reg = icmGetRegByIndex(processorP, 13); - setSPReg(sp_reg); -} - -void ARM_Cortex_M3::makeSTRegister() { - OVPStatusRegister *streg = new CortexM3StatusRegister(); - - fail::simulator.makeSTRegister(streg, "sp"); -} - -void ARM_Cortex_M3::makePCRegister() { - // ARM Cortex M3: PC pointer is ID 15 - icmRegInfoP pc_reg = icmGetRegByIndex(processorP, 15); - fail::simulator.makePCRegister(32, (void *)pc_reg, "PC"); -} - -int ARM_Cortex_M3::startSimulation(const char *app) { - bool loadPhysical = true; - bool verbose = true; - bool useEntry = true; - if(!cpu->loadLocalMemory(app, loadPhysical, verbose, useEntry)) - return -1; - - // application is loaded, now fill the callback memory with program data - fillCallbackMemory(); - -// icmSimulatePlatform(); - - while(1) { - // save PC - Addr pc_ptr = cpu->getPC(); - - fail::simulator.onInstrPtrChanged(pc_ptr); - - // simulate the platform - icmStopReason stopreason = cpu->simulate(1); - - if(stopreason!=0x00) { - // was simulation interrupted or did it complete - if(stopreason==ICM_SR_INTERRUPT) { - icmPrintf("*** simulation interrupted\n"); - } - - break; - } - } - //icmTerminate(); - - return 0; -} - -void ARM_Cortex_M3::makeCallbackMemory(size_t sizeText, size_t offText, size_t sizeMem, size_t offMem) { - mem = new unsigned char[sizeMem]; - //mem = new Int32[sizeMem>>2]; - textmem = new Int16[sizeText>>1]; - offset = offMem; - textOffset = offText; - memSize = sizeMem; - textMemSize = sizeText; -} - -void ARM_Cortex_M3::save(const string& path) { - OVPStatusMessage ovpstat; - - // save registers - // FIXME: what about reg with id 16? should be status register - for(unsigned int i = 0; i < 16; ++i) { - uint32_t tmp = 0; - icmRegInfoP reg = icmGetRegByIndex(processorP, i); - icmReadRegInfoValue(processorP, reg, (void *)&tmp); - OVPStatusMessage::Register *msgReg = ovpstat.add_reg(); - - switch(i) { - case 13: msgReg->set_name("sp"); - break; - case 14: msgReg->set_name("lr"); - break; - case 15: msgReg->set_name("pc"); - break; - case 16: msgReg->set_name("sr"); - break; - default: char num[3]; - sprintf(num, "r%d", i); - msgReg->set_name(num); - } - - msgReg->set_value(tmp); -// std::cerr << "save " << i << ": " << tmp << std::endl; - } - - - string stmp; - ovpstat.SerializeToString(&stmp); - ofstream file; - file.open(path.c_str(), ios::out); - file << stmp; - file.close(); -/* ofstream file(path.c_str(), ios::out | ios::trunc); - if(!ovpstat.SerializeToOstream(&file)) { - std::cerr << "Error writing to file " << path << "!" << std::endl; - }*/ -} - -void ARM_Cortex_M3::restore(const string& path) { - fstream input(path.c_str(), ios::in); - OVPStatusMessage ovpstat; - ovpstat.ParseFromIstream(&input); - - for(int i = 0; i < ovpstat.reg_size(); ++i) { - const OVPStatusMessage::Register& ovpreg = ovpstat.reg(i); - uint32_t val = ovpreg.value(); -// std::cerr << "restore "<> pos; - - return val; - } - - void setFlag(int pos, bool newval) { - uint32_t val; - uint32_t bit = 1 << pos; - - icmReadRegInfoValue(cpuP, cpsr, (void *)&val); - - if(newval == 0) { - // AND with 0xFFFEFFFF (e.g.) - bit = ~bit; // invert bits - - val = val & bit; - } else { - // OR with 0x00010000 (e.g.) - val = val | bit; - } - - icmWriteRegInfoValue(cpuP, cpsr, (void *)&val); - } - - bool getSignFlag() const { - return getFlag(31); - } - - bool getZeroFlag() const { - return getFlag(30); - } - - bool getCarryFlag() const { - return getFlag(29); - } - - bool getOverflowFlag() const { - return getFlag(28); - } - - void setSignFlag(bool b) { - setFlag(31, b); - } - - void setZeroFlag(bool b) { - setFlag(30, b); - } - - void setCarryFlag(bool b) { - setFlag(29, b); - } - - void setOverflowFlag(bool b) { - setFlag(28, b); - } - -}; diff --git a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/CMakeLists.txt b/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/CMakeLists.txt deleted file mode 100644 index 5f7e4dea..00000000 --- a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(SRCS - flipBits.cpp - model.cpp -) -add_definitions("-m32") -message(STATUS "flaky ld flags: ${HOST_LDFLAGS}") -add_library(fail-flaky SHARED ${SRCS}) - -add_dependencies(fail-flaky fail-comm fail-sal) -set_target_properties(fail-flaky PROPERTIES LINK_FLAGS "${HOST_LDFLAGS} -m32") - -target_link_libraries(fail-flaky ${IMPERAS_VMISTUBS} ${LIBRARY_OUTPUT_PATH}/libsal.a) diff --git a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.cpp b/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.cpp deleted file mode 100644 index dcd14dda..00000000 --- a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include - -#include "flipBits.h" - -void flipBits(const void *value, Uns32 bytes, vmiProcessorP processor, Addr address) { - if (address == 0x019e) { - *((Uns32 *)value) ^= 1; - } -} - - diff --git a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.h b/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.h deleted file mode 100644 index 5c52d358..00000000 --- a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/flipBits.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef FLIP_BITS_H -#define FLIP_BITS_H -extern "C" { -#include "vmi/vmiTypes.h" - - -void flipBits(const void *value, Uns32 bytes, vmiProcessorP processor, Addr address); -} - -#endif diff --git a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/model.cpp b/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/model.cpp deleted file mode 100644 index 0e03f31e..00000000 --- a/simulators/ovp/ovpworld.org/mmc/flakyMemory/1.0/model/model.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// Modifies values read from or written to memory - -#include -#include -#include - -//#include -extern "C" { -// VMI module includes -#include "vmi/vmiMessage.h" -#include "vmi/vmiMmcAttrs.h" -#include "vmi/vmiMmc.h" -#include "vmi/vmiRt.h" -#include "vmi/vmiTypes.h" -#include "flipBits.h" -} - -//#include "sal/ovp/OVPController.hpp" -#include "sal/SALInst.hpp" - -// Model prefix (used by vmiMessage interface) -#define CPU_PREFIX "flakyMemory" - -// ... -// Cache object -typedef struct flakyObjectS { - // MODELLING ARTIFACTS - memDomainP nextDomain; // next domain (FULL model) - memRegionP lastRegion; // last accessed (FULL model) - - Uns64 count; // intercepted reads and writes - -} flakyObject, *flakyObjectP; - -// ... -#define BUF_SIZE 30 -static char tmpCharBuffer[BUF_SIZE]; - - -// Return a static temporary string that has the digits in the passed string -// separated into groups by a comma, e.g. "1234567" -> "1,234,567". The result -// is in a static buffer so it will be overwritten by the next call. -static const char *getCommaString(const char *string) { - - static char buffer2[BUF_SIZE]; - - Uns32 length = strlen(string); - Uns32 count = 0; - char *dst = buffer2+BUF_SIZE; - const char *src = string+length; - - // copy null terminator for comma string - *--dst = *src--; - - // copy remaining characters in groups - do { - - *--dst = *src--; - - // insert comma every three characters - if((++count==3) && (src>=string)) { - count = 0; - *--dst = ','; - } - - } while((src>=string) && (dst>=buffer2)); - - return dst; -} - - -// Return a static temporary string that has the passed Uns64 value shown -// with digits separated by commas -static const char *uns64String(Uns64 value) { - sprintf(tmpCharBuffer, FMT_64u, value); - return getCommaString(tmpCharBuffer); -} - - -// Utility routine for statistics reporting -static void printStats(flakyObjectP info) { - vmiMessage("I", CPU_PREFIX, "TOTAL ALTERED READS/WRITES: %15s\n", uns64String(info->count)); -} - - -// Cache object constructor -static VMIMMC_CONSTRUCTOR_FN(flakyConstructor) { - //srand(time(NULL)); -} - -// Cache object link -static VMIMMC_LINK_FN(flakyLink) -{ - flakyObjectP flaky = (flakyObjectP)component; - VMI_ASSERT( - vmimmcGetNextPort(component, "mp1") == NULL, - "%sCannot accept a transparent connection", - vmimmcGetHierarchicalName(component) - ); - - memDomainP nextDomain = vmimmcGetNextDomain(component, "mp1"); - - // sanity check that we are in full mode - VMI_ASSERT( - nextDomain, - "%s: expected an opaque connection", - vmimmcGetHierarchicalName(component) - ); - flaky->nextDomain = nextDomain; -} - -// Cache object destructor -static VMIMMC_DESTRUCTOR_FN(flakyDestructor) { - flakyObjectP flaky = (flakyObjectP)component; - printStats(flaky); -} - -// N-byte read function -static VMI_MEM_READ_FN(readNFull) -{ - vmimmcPortP port = reinterpret_cast(userData); - flakyObjectP flaky = (flakyObjectP)port->component; - Uns32 shortAddress = (Uns32)address; - - // read from real memory connected to mmc: - vmirtReadNByteDomain( - flaky->nextDomain, - shortAddress, - value, - bytes, - &flaky->lastRegion, - MEM_AA_TRUE - ); - -// flipBits(value, bytes, processor, address); - //fail::simulator.onMemoryAccessEvent(address, bytes, false, processor.getPC()); - - // increment counter of reads and writes: - flaky->count += 1; -} - -// N-byte write function -static VMI_MEM_WRITE_FN(writeNFull) -{ - vmimmcPortP port = reinterpret_cast(userData); - flakyObjectP flaky = (flakyObjectP)port->component; - Uns32 shortAddress = (Uns32)address; - - //flipBits(value, bytes, processor, address); - - // write to real memory connected to this mmc: - vmirtWriteNByteDomain( - flaky->nextDomain, - shortAddress, - value, - bytes, - &flaky->lastRegion, - MEM_AA_TRUE - ); - - // increment counter of reads and writes: - flaky->count += 1; -} - - -vmimmcAttr modelAttrs = -{ - // VERSION - VMI_VERSION, // version string (THIS MUST BE FIRST) - VMI_MMC_MODEL, // type - sizeof(flakyObject), // size in bytes of MMC object - - // CONSTRUCTOR/DESTRUCTOR ROUTINES - flakyConstructor, // constructor - flakyLink, // link component - flakyDestructor, // destructor - - // MODEL REFRESH (AT START OF TIME SLICE) - 0, // refresh - - // FULL MODEL CALLBACKS - readNFull, // N-byte read callback - writeNFull, // N-byte write callback - - // TRANSPARENT MODEL CALLBACKS - 0, // N-byte read callback - 0 // N-byte write callback -}; - diff --git a/simulators/ovp/setImperas.sh b/simulators/ovp/setImperas.sh deleted file mode 100644 index 72d6715a..00000000 --- a/simulators/ovp/setImperas.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -INSTDIR=/proj/i4danceos/ovp/current - -source $INSTDIR/bin/setup.sh - -setupImperas -m32 $INSTDIR - -export PATH=${PATH}:$IMPERAS_HOME/bin/$IMPERAS_ARCH -export IMPERASD_LICENSE_FILE=@faui49 -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$IMPERAS_HOME/bin/$IMPERAS_ARCH:$IMPERAS_HOME/bin/$IMPERAS_HOME/External/lib -export IMPERASD_LICENSE_FILE=@faui49.informatik.uni-erlangen.de diff --git a/simulators/ovp/statusmsg/CMakeLists.txt b/simulators/ovp/statusmsg/CMakeLists.txt deleted file mode 100644 index a3ecdadf..00000000 --- a/simulators/ovp/statusmsg/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -## Setup desired protobuf descriptions HERE ## -set(MY_PROTOS - OVPStatusMessage.proto -) - -#### PROTOBUFS #### -find_package(Protobuf REQUIRED) -include_directories(${PROTOBUF_INCLUDE_DIRS}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS} ) - -## Build library -add_library(fail-ovpstatusmessages ${PROTO_SRCS} ${PROTO_HDRS} ) diff --git a/simulators/ovp/statusmsg/OVPStatusMessage.proto b/simulators/ovp/statusmsg/OVPStatusMessage.proto deleted file mode 100644 index 63b2f629..00000000 --- a/simulators/ovp/statusmsg/OVPStatusMessage.proto +++ /dev/null @@ -1,10 +0,0 @@ -message OVPStatusMessage { - // Registers - message Register { - required string name = 1; - required uint32 value = 2; - } - - repeated Register reg = 1; - -} diff --git a/simulators/ovp/statusmsg/protogen.sh b/simulators/ovp/statusmsg/protogen.sh deleted file mode 100755 index 5e6f0fa8..00000000 --- a/simulators/ovp/statusmsg/protogen.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -protoc --cpp_out=. FailControlMessage.proto diff --git a/simulators/ovp/test1/CMakeLists.txt b/simulators/ovp/test1/CMakeLists.txt deleted file mode 100644 index d4766780..00000000 --- a/simulators/ovp/test1/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_definitions(" -m32 ${IMPERAS_VMIINC} ") - -set(SRCS - $ENV{IMPERAS_HOME}/ImpPublic/source/host/icm/icmCpuManager.cpp - platform/flakyMemory.cpp - platform/beforeInstruction.cpp - platform/platform.cpp -) -add_executable(ovp ${SRCS}) -add_dependencies(ovp fail-comm) -target_link_libraries(ovp ${SIM_LDFLAGS} ) -## OVP links all needed shared libraries via a runtimeloader -set_target_properties(ovp PROPERTIES LINK_FLAGS " -m32 ") diff --git a/simulators/ovp/test1/application.elf b/simulators/ovp/test1/application.elf deleted file mode 100755 index 395dd5944480d16670eca29d0e76b6733388c166..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88526 zcmeFadw5e-)<3?_C6}gYlinb`LE2C#ZGk`wBA|q{J*|QkK^zg(QxHwj(R!JY8GUWq zqJoz(ZNW(|Ac{IF2rc5sMNE~^@rG{#&I|}0>kJTWX5Kkz3ps6}`F{2Zl`@y_^ZuUa z_xzsUAED35x$U#|+H0@9*4k^Yy{IW&Brps^M*guRm(aTpaTMWrd>lhqLR3Y>jB_qY zCJFR?brF7xoG61si*oefFCFxI;-o*3e;YR7b|WDgdh3ili~dF_5T!tr0#OP?DG;SV zlmbx-L@5xZK$HSe3PdRor9hMdQ3^yU5T!tr0#OP?DG;SVlmbx-L@5xZK$HSe3PdRo zr9hMdQ3^yU5T!tr0#OP?DG;SVlmbx-L@5xZK$HSe3PdRor9hMdQ3^yU5T!tr0#OP? zDG;SVlmbx-L@5xZK$HSe3PdRor9hMdQ3^yU5T!tr0#OP?DG;SVlmbx-L@5xZK$HSe z3PdRor9hMdQ3^yU5T!tr0#OP?DG;SVlmbx-L@5xZK$HSe3PdRor9hMdQ3^yU5T!tr z0#OP?DG;SVlmbx-L@5xZK$HSe3PdRor9hMdQ3^yU5T!tr0#OP?DG;SVlmbx-L@5xZ zK$HSe3PdUJ|0@bSXCxm2q2JdK@)?dVa2&z$-#9-0r^AQ)W0#)&0p~yc)BAre|Nq53 zDJNy00e}6=W6V1~Ai1$8b=Rw}dtPukNG|a{De%`VR<5)nhmt6W_CCIW5QZVdxe>>^ z3D+fDpVqz1(d78rvBe(aC1$?+-1qD~TI*l&yUi~9NOyW_aut29wUUWs(#Z4V8O+sx zIjWJ$E)oyGk+16rDL=n~>+B_5+B)5S#%!vtE+d}u-tWzLMzrs8j{FWA-qI3Whr3LB z$oXzvJK1e2C(;LUg+#c=#LVuL@?SWJbcdY0utK_uO%oFrraKbL6Rt}Wh_qBrz|(9z zHQ=eCJWhF9ECJ z%&fo(j3gh@zDu%rTs=5k-usAxqsdXfmf~p^G*aTl_`Sw=d7-}D)KOm*yPuUpVY8s# zscNwZwGL(zkv7X*`=RfRHm<$8%&@n-SGLf08qvZG$ApgURZ08J0xO-uSE`--k6-;# zW|gmad__D~)UdH#E5xC#*U06)k8{jsg<4IFg>PbZsG3-dy2+lwx-^Y?zzlTIddvbX zlkRABv}{c5CwDR)dp}vyQoH>AESz6>JailXy$W1aomjrozMbDS|2PDE~c(Moey-CFt5~E+#qc6a* zXnR199QrIxw!&sC0Ybumqg9&%Eol}00D&9V~>!-EtDMCy` zVpE)plU^PojiC&jeU`!?LSKONIt z-dmIudCz*{T8=tm8e>}9Hg4aO1X^f)G47Ina`W~*_WRe@W`iE~yOSiXfstOQk7?Fb zkvv9vrk<11I2~&Hn=|fQ+uFEuuDf(WUPmmq2wah|NxM0%DZR!5kLt$|m`G53#Tk!%@65YV8?g1!l(Fb*ba%aZpC>8Ky@i$BPrC0Q?n(rcG z`P<2N_#GlK+&}+~lpB3s$uZ1Wo*t3E%`82)D!-8@gUWR}H&SBsS>T58J^g3ohm{gL z@Oyy!lKTtyU%0Brag73bId5o9bgi%(nlx=C63=TkC9T`!k309qsyKH{vwj9I?GN9& z{}$m9KWH|yuw(R_o#B|~_?BlkCP_AM8R#)1zA@f?dwbkD=T8rPFTD`c`sa;f`bkAi zfBfz{?~gn8tIA`txm!Q|n4H_0C&alc`kiYMTPH{?e?;zn~g-a71o9eMElscSq#)Hy@E*I5w4pLoLH3H{KO{l0uAg>!-8Qkqhz7+w2Ms)8iWs z$s39&PW!wuElnGXB^%dNyT{K;$1jfN>ze*eyW(1wfOB6yt9?o1N8hF-tsCP{l$p7C z`HaNXZx32YOfJ*Ar7l?@laldV6L?xf0%e-Wn{1)~L|Kpj(Tis_t;Ld)(=;WmJAYQw zoGEA<6Tt6dnuzq}(}^v|GA)vZCI}%g|;n_RJB{=2XZ)bdGD)SdG9tx=NjY2Xk+MzBNNJUk9%STO>Nit3Hi7WA#E zr6Zxd*QuqW0?@USg$l_SlP$z-DG|ElA}8BzoNt_#)y2#x5;0a>#_8Hwnmmk`9Cc93 zVa%lbPZ#A0n=o0R-15rsErJejNN!EPw97aj@KcP_06nMc)HcZ2WPvIAL?%v6!K30e z=;e`d_iY_*@i^g`4vINPEi{mvSj^kyB!C83omN^)xo zGD|*_dFy8~tRnOcr4Z?RrY;6`(4OQCOT4rfg)}nthA!jO1$~l}eogz3_MdT*1^qUm z{m0(B);M*17gK1QsmTXS8(>#cShPJ9{zzMvE4_F4qEBf@(k|n*lrxM|0ej}RXa{Wt zzDK_Sf;jWX{)kn2e?(SnzeuUj|2F+LzD3t&Xl=9a^dzPpHN`iQDK@FPo|tbDP`4`m z43#%pMc%ADqiNPQE|83jra{v(rYTV}b3~d_o7nnICb48o8kSYY&e0!8>CHVV0-2u; z*>A>(Rgr10cr?v)6lfaAG?T|JF)Trkud8Dqy-(J&`1RMvoqP4(*dQMp8=S=TXe)ZY z)|U5_uHz*QpCIr-D;p=22yH@IH8YpO|GQ7q42{#7ATb7;)UrM{m>c_LAeK#NOlTu! z%BSz!_j%?C$-mZZN_7>V)wF3FOC%%OqH&LDGD>Cxk>=MXHZzvbGhgyUc9q4t(|EJu6=e}pY17Pp48)iFxjPRpma{$l<@0RSL2zab@%1RdNi$?wqo!GrM1qZ zY0_+hte$@jYQsoUFy@|2Y>jVAbf-G9g};vFt%D%lh&g+t!~E9i*) z`TaNTM8DhxuFj&p0emdFh6MD?12dIA+LUqz)R;-~ZPG*ac)BcUT{!g7K}vDv60C!` z(>7Ax8`D(N|6!zs;NDN_G;SkwA(1|;qZ~LQh4;uM-gDLTe{=}~ zk){HFk`rlx2ee6SOLv$vNxq>eeEz!~N$V0}KR$kNv|X@mh)RLr4%&maKpNe=Ea?pG zAv&5epm7$LGBcA}7z>psyp>86V!kZvUV0Mp2_sb-lL?7P<>4176?bmO>Mvws9Vu56 zTKD$oI`3BMd~b(OsjuqHnC3N;ZGGQ4FKgBl3b);_)L-7)t;{x1vo)e)C?=P+%yAEu zk)+SLzDst@G`2L^`IB^1Foya4^B~<8mu9$`qOr}I0u`0kL@Cb!nsEd_(zohKW6Le$ z$W&Y3lJ!RXzV;OT&N%5?nLL?2N=9?tM#yMe-}zc*MuvE&Xq>4njA&R`3{>CzlZ*}y zQhl>jk<;^cQ0fA1&M80TjxU{5M=l8ZOwZ0QBD8XZ_!rWB1|~lA>4P`*vw3>34Ock65oI)lwO0jr+pUb zsS&CxcWTo2R4r4K(L5H~G_K^h2YNdeWsUd_I(5Y2SXFzOH@?6u%_aq%MnwnTHtr#@ zI73rVD5m_V=W0T~-8CB1sS2hwZ_&Ourtloa@3pg|%VeO;{QjqQhC}xrNNA*Q^fQtg zPn{lJMyJ48@m7Ry!=ZCmjHDspRnx!d5tO6j1CJ5UmI^(3vw&4ip-c!fSFizLx0q$t~A_rqgu@D1SScnY+z8@{bZ{I{urvQ4+34cNp z=mJ|VscGS99n~_7Q`(EU;Tx;1MND>VVL~IgxHPG09_aV#y{6_%`ke5RfwjaG_oyDO z=t;?VW@QF^3u^>sc3L$w6#EY!)!s=>hXb)(Len^KQ^hzk?G)vSn0JJl(2=)|(~f(< z|Fw&{zLg!d79mfufJV?n)tvIesUz!9+#Yp|NOE(fifdCJd1 z3%!1jO3yS0WBK^>HpLQ-jEFl%*;6$k{f@>nac-w026A=TzW;1N)`Wig_PbZ`+i96{ z%S>A9GKvN5wOfQ|uPAd=DPtKaqo!qi!aXSS>b)JpC7No@u;z7`k*FoNEC}?DShT_L zY&K}+b=gJLYUw$dhc!>FrSE-7FDf){zESuv5X&SqfZq>VVT0XKpVXwhafAB2)snD@ zs}6^5KS(?-_<`=SuL+c@rdTKps_7zj1Oqyy9Hjbf$v!$q;-oW}5fQ1f?!91mK9Rnw zAJg_~@SgZT2MJdki08@*w4P#EAxRx%n%2WiN^jM;Aqo4P)f!i4@5l9B@_jCno!mI4 zb$jq`{_7x#T^QhFg?z1Np~S?}d4x^+NquQP>suWVEa$tu5}{+m%P;0vBo0 zZR+|#XJKJE?Zj-8pMC@$15UZ)VWZ6$9@DZXcn=4Az*3fnHdr`{jmxq>qA!T_dOhr& zfR?9qslD7fD=eY+fR|(DX;VZ3T_>odXTr3V*VJ2J9gC%7nv>dI4&FoT_TL3K&K@AF zv8ilwvL{J^eXIC7VigEULC%oS#GZV~?(8jsCCJVm<6`EHX(5=eIA%UC-vU;KSp1a^{5n1aey?5WWeu&HZW~@s1DDX1N2I`pYfdx#GV4WV5M`R}T zAE&H^Dw&yw@~hX59U(v8y#)G7;ydiO_cFPoH8 zJ7WE8fb|pK66>J0PnvT$bn1h|<}XHUYc{bl!;!X$&dbB085nbsc`D@Dzsz??-+0W{ z9683eSL`>Rq|h0|Vqa2QsyoYMYy78>L$KiGJ&DDha4`Jq7O#Y?fx& zEQ(HCE}Fy<$xr%z32e6bn}u-bt9?{1(z4&m)+fWESN2`jRh+aJBk_rTl>*g=(hox4 z(3$7|&X(HdoVDNBigBS>DD(T>ZzwojVMl@D#w#^C>D%f2xt;2wfYUgYN^19dTi@@U z-^#A_7Qr~_vb{2*jox$q=h^PxFKHq=+vTK1!*sU$M1LD>3x!TIyZqqT?8HrELUN;} z=dTY_Ue&>~G90?elh_j9mZaG68RBs0{X>*rSqJ6I5nDPOdUs!9vtHpb%BxlT6Prm+ z7-Js0G3Nz6>VcoP_OjvG4$Tz z1Eb-6qLdsv3Lfp91y?}ZtCUeG)LIG%FC17XtULRkeFKr6j34D8;G{+c#$Oc=0mU10 zfg)pTQp+g6hk3+Cdm^-ccQ~X!KSebQVkJhiO8>uXPQWT{fjQCAo$}Q?9@&R)Mqf z?MR(Rq4#5&iPQrf{g^MNWfT1A!=ZcMAMKwT4$bxK6FAG;rxV;$vI*vk59ELz)yWMy zKo1`p(|q@2_$=TPa$vrg&}8fTwR8Obh@4`*w`CknO=wJQ8nb!UnZ&kuw*_-w_$0y4 zH^1K{i!1Z{>{Ia47u%oex=0M#gc4_tuPi zauQr$`_bZuFmG>6+(i3@&fAAWzdb}ImBB+g9J=rQDOp^QT$kK%^=b8_{L}jc*0K0W`1)Te&oVcmSwV+m{3dO%aCK@%m+@> znGx;fZ{-cnaA?IrYH3F9*EzEzb4|?iJ9nlweRTSsoTvPk_3R&&d7^FSr&zn9I&#kG zDcLLRR6pK-n$qmf)1Vf-1B@Zw%U+f6YllD4t-&ZK(>&)lzLB(!di@j8GVXmQJE3to z#>ZQgy6H8iBQ}kdu0c&ezw>cIlEA>0G&`*C4~G`O=Ba)c@1T!~N-gMxT!&FvZJFhz zK50C~%F1k9Co8KeZT1DYj;ye>*?CXCh{D@#1!W>qD5EAPFogAbNqZHV*I z($1l68;NE0>WcFxAIhpCJuHhmF-x>dT5fx7>z+6LwD#&l${N%Htn~4eLhIXA!bHd3 z`$)lLujm+`n|G?K<7*iUrMXkQUYXS1?O-OUgJ%7EHg<|lo@lno1=jK&4XgEdWqx|6 zjFm&r_~K5Pe~@(F?RY1Hn3-93izTwf$YXU+s#OOU@q6#``HRnYSy3PPem})R`thFR zp7&Ptudn7B*hZ#_kzO9=n%NenmE`t#$wa`f1nkOo;dj7kpZ_`YNV(@PmE)m1{@`uD zk4(BpG>d!hB2!-S9Z=TwK2}yC^E--rFDf+;ho0PDT}D?pi_iak2JLGcEM1Q?2$v^GI+ja_N ztd}t#mq~(gknh#mjo#xjpP;kH`#AS9na^;Sp`3L^=^o!V@RBSn{nY!m-(A-4$2+~d zO!CvWb30Dp-RDBHK=FRf=fP8ACHd#PpW__C)CLY2x>$~1`63{>egKUK{?Yc=w{ums zLR=Nou*FXLHadGUm|!wbg2`Iunnv=hsm?S$bGc)&gPG1ttrygw_&l`3E?9)8grze7 zMS^4e;B!M2JsFF}57rLG4yj}RSfU?NOC*qP8$bB$&=-Mt-S|Q0FwuV%NVxGOdwd}8 z#_@yCTv*f-zo4RL>Wy}pPygm?7j$7_{aKF1$cXYX&ZJx8ApUZZmhRKQhnQPpo z1IIp-jf>HSW>$Li0?D0rl9^SEc_Pu@Ec3Ccz`{95^v~?+3?wZ0JixNQv2QA20tI$p zhq_qQmA$AKb@~6-by)?vvMs$p%!8m8rPWLArE7V?1zP8CB~ysxs?T>U?O5wza#DrO zwk_gqA}jd^R<9-5X(D<<)!BQ@Ni2mTv7`yVKQBFu;~`ZK$2GxgyxU3Fn{2{$!jT`? zjm$)qbp61F{bR6poaoDQGnRs8PJ~@Y=(tJfcx>UV<6_0}5qu`nQh)QBg{~i1OU9d| zA@fb9ftAR`kNb4D)Cur3NIRXJ`}K2A{5u@VTzqfg0BtzH)aayT~=4#Tb*F1>+Q@!feC!f_ah9?$;a zddl+&)}FP4MACG9610(VbDy;34sv~^Jse@O$29U%?Zwy6J#{yCZLGl3p0;q91`p2OX?bBd=a-71JI1CNhmke|BPRN8u&yM%rt(zNza$?IaaEGiU=hHGvC! z#EpR#(LxWgTJ$w@hqzW4EpTG}V%*Arj_GyWJ_g z99;a1d4I8i&%V0=2*9LxRHmm@6FV*&oA-hnB-k{Lm1C}<) zP-h4KY8iEq6!X#xcxJ`gW^Vft+1x(4l}yra?J8alFARhD7j5%{9dl`PgXIPLh_`{x ztna8d3)*HzI*VABn^5vEVT}E1W@cVXL2HUgS6@u)$BBA(`dJhFS}V6{+vqrQ3LAxt z)^Cf$hWII8ddMV=#As-be(0qAH(7}Q(Y0`akGcOg&|V{XBc*6RV;x!AT1#ma>3x19 zFMWRzGz;su)`B`qKphs;*?WneJX$+XT&K>dQPL=We?lRO5HVb@Nia@=cxaENX?nr~~si zd_yF|dWykfVY$Fe;H4JerVUffR0?LmM9oWU6zpgjUfMB8EE<`)mt^m@Q~tPCpfJAz z-|;(21Pv&cyA5?Rw9UNq;vmHm_uxG$llBaY`{@;Z!o!}R-rw1~Q^C{o`-^rbZq~aC zg(R8DxNY1xScg}`PXDgH-hR%fcTdMU-R&7x3s;>`Jkp)E(3Tzt;+~rC(@>RGR@ef zZJq=EVWkJGJ_j zb<`Bs7~66bG-0Ipu-290*C}4Hk#D7M7R1-{@8pYMK9zjdiH<|bT-z_1U{F&>d~&s@|1>eGXlrCZ^EMj4G- z#wJjjT}MlzwfCZCn{=U;WYK$KK73w!5O@uYjCEeRO~LKOT?d1Vp(b?VZN2*{!L+#^ z>m@6dajD&*-DKz{StH*L%MpCc3goqQyY2J)54=4x@~QmbrEM5}5lKLCj*Q3`2cN|l ziM#d>G1urZSR=`U92=bH4xWp}wo*@%2oMtS>rpe&2 zk37!`@eR5LTi@PV=(FsD!Lf#iL|gC6b-ZN-VP=a_?zkHo89bGug(*Gj!flNG37n_$H%E*EIRp zD^F8Ppr-$hU7z(Oab*I@ujyaDi&|$fu*}Be9&5q7;#!$Wv2La?u8Fb6y2{TQFP1lHV@Gwr+(z`AO|f%6b7El^saTG@blt#_A54(-RF8KJ(UJ9yOzkZC zgp-~M(~&VUy6D)-_v)L|H#5QT)dt~22`zO@xIx$>OvKtsgzI@}{J=)R2}th_QEuNO zN4TAi4okA5K~rzC6C4R=gdDchYfe zQpR!jgPb&bREb+rVt)U?jzVFafRzK8DX``ZcoVmTLnjaF-Qf^_;G}G{#s=y+Qxzjs zUg)GU{tO*|jMR&<>^VR2ZQA!{w1SZi4;fpSYcLCd-SdMp-i^4mGfZ}TqpopsV>tBZ z1E3!~wz)2LGuzEbJBR83hw|xwOnbPZ^d>|P!vYCfRfzMInHB9q;3V|@Bz6mI8q~o^ zt1d2wJYXd1i!^lUTLgiwO9AhBSLavyT&3r!HiZtLD@|(-a=u91L61)mOfqwgHGj|> z4lO@O`5_$o%K?oN<(9iG9J=cu)lY^NM*0@~``BrE$4Dn|{j<|!FdlC7QmfnW5?2_v zb?h0;{9u8Y+ry!02bt-KTM|%PF}&ea=EOqFY)!*#<_sMx+ARiXz6kF8CETema%q>Q z_3Heqy-cB|iFG6X$%Xc&heNRknZga2JBLH+gIZ{fn;eYv>7cfi3+kD)Dt1OAf%nMD zNOugFh3SAxab#V?XEGHl;c##k_vvZ2S-VBsu*R=x(QdgqPvd2q5gXD_oI$xT9Qx(} z+uAN@o36HKaeupC)0{7$+~htl$!EHl>6!+%g~qW&N*_M3`w|Uzcwh4q#64>H&R~^jSSshOMOLFf&Q*? z2>oRBcGwv!y3Vd8Q~SKFdq{Rtzw;;Xk}UodQ7R_Ss-G4ro-mcS(y{v9C26r8mivyP zw`mRSW$p09O!IEvNV2l4EPz!hrt{fix_)~tpxnuM>HFzkaZTmDfVP-Sp6-qK(O9ny z(dVZIh*?}sF+tG0e7}E=z>I>+3Yma>cCE(`Y^<62ZO1G6nTI}w>}#=o{Pku(G1D)z z?<0BJP7Nq!NdD(Oam}ZGtb{TLGhWbl#9UG zzVR}35F@X|ypKeyr(l-)2xmVZq#kbS%VJCp*xK*IuVY4}IS!$>bOC)%q;C#Zzw5|} z7gR&cITd)ANEa{gLOEu?dX8iXVjkwTS>kpPa~s(#P#@vtod75O)bF7Z)>qZHlY(`= z;@&ff44o&k^_6w2N_*d(+$kTomG*Y!cFL!4PMy;!cjLTZE`!M1H8M)Z;GmLUha=V@ z=7P%0-@c3uC-~|UeDw*wDiH4zcZ&DjT~K*nrN`JEV_{@79I~~ki?hoU;9YxICjAMHT^k$ML`$!J8JJ#IIqt3t9 zP6ij{h}(h3YvLL)r*ci@YpBg8uUY-t>euc%a~Gw0t|PZYCH&E!3t3zm_W9v=$-;_N zI9DXOy*|B#hi{?>J_EXsVDv%vFckN8QT_NMAAENpvbUkQ_q!{e{{hdb5B%#1<-K0& z2d7?O)m`bY8r5D^V7&@{#cSMU%)CM0q3^40ymW(ycx04!l+dyUK?Qj{U*7Jx!!c3f z)ar9jAVT=t^!c&O{Q2B_=bU$HPLix#lt~G1ceJLu?Yx)Xfh z+qjn<6zB8lxq<-CK$_!5@lWaF!G%VdLHP(IX?VNiqclU_H(llDt9g7yV)3o9j5&ztRH~}8v$+vp3qaplSPzx`P!*&a;g-pZ<^UB&zpXs^M3dbag)2#8r z3Q<>x)8T18lKN9e3g(Dv-^o-mb)olp$7hZo#OFmsH895(-z5HV|2y!^Pd&C=$4|cZ z_|}-&v(Ayy)HfY(+BsiU_eRI_Xlc0vyGKa9J#_2~$1$-%{9J5-rv~z10g-;=Ste^& z!rP=@lD;B!vtv!E;5{nqJ3q$prL0~2fuG8alUgQ6aFD=Zrq!4NACgae-XXvmEEYG5 zJ>oOspZw1|@+%J6+kHI>W^ajqz?+-IV~aocQ;TYDiN=R|GM1#RFl~1Dlophqe}q9R z;E5#6GOOjz z#Kik4uda{yn4fHSVZDWQDf_dejm~E`jvuTaNX0q|k+wVOZWJQDRg%!kxm6!Ytn{@3ijujRX5zYKYY6{J?%t=tO){Qori~n>4o8?BITV z73{RzAYocSR7pQiV};sB<&Ru+RW-J`8=Rjf1CcPtgWU#mQ7CRiK$=v{s5o& z{SNKSul%^$Mt#Z;;EqfSdEckDwsgRmU3IXu$a6y2kJY5rRj)f-_DxCz^w!jlQp}XI zvHt}z&o=2fXLIQTCtqK?1iFZIBTl8Wy{rqr>T&Q_Iu8cau@A$?ueI(e@uY91c!*@` z=RT_tSu>z`(3&xp9w_q66)O6jtFMP8Po@REudk)rjpWvrbOtnfNyoxR{NdDezTU=Ky|Zb z+_e;{^?-0Coof2;+dW%&+i!NfBXBQXCEVb@9{#Nx5hcTSBCh`;r88~WXYjhywk|Ar zMYM>|`Y1-&*EHnbe@a;Ize$*J>5H`&Es*-GyEWA!hC?0j=m8Ea;OgC@ZGxX+cA`U! zGOW>9BCWbW_g&Fab9U4DAHDlL5F0zgKLb5ZB%6Z8RYGI>9-%dr*01(oC(OZ{Lexev zIjPk4%ZRPL>ofm7RoRZLDh+m$d>CMLn!ukP)xrDdOsz3KZJ#5|^I)DMz+!kH)62RO z0B7|;J!Z92y;)UDa3@~azR}X}T21$yY_E+C=*Z^*4fi|Q*#3@iPvuphlNlOy-&xkp zNV5m&mw)qRRk5(6kHNE{vuumrk|h38k!NzT26J#&p%;%| zrNxSKnirg@eZuj+gG^26B011CR%T{#$KHW>t66vla+URdT2|hJEr)hK=-~gyH{U^~ zo%Mx7{tGrpBDo&Ayv!*)1DK~Sn1aVOTF-tVokER?Ku!D+>Ouu-7QBiPxZbksdPqzJ z?%x%-X8`x$g>ow4o;JRlEX;v@a&v-F@$NIyLl?~Z%X`-;o_FIRTrrBgVHo)Ou6)z^ zE2g1 z!bVb7kaw)IgFCO%H##S(O^cRvHTo{(-t6sliP> ze%Mike_2ag+G0QCdxhe#dYoWcV}~}_Ui*7LR+J$F|LEg`Wo)s;a@nYZv1C`SuKW^q z;pIJzMAGgXeIKSV0I=tnU@SkTpuSx#Og}LJJ23ugcn*>wRiOHgOtwNE5ozItz2`2} zOgoC58hYr_QedM}1-@jb3CEyAus5V`C3c@`wcj|b!UT!qn;q$?D;=MUB@)9oh$}@R z6@cq5Sx*+@gwZv8<<(ojb=pGl@BTY`ZZ64S{^(DhA@7Ob8ws%T;c?@3>0Etz~& zY!scno1E>?;ZEt%+D5n!D)=g>dgt!Cu_THJzBC3k=EMouVlUTS&^2j z=-J7|4|2m#mHyXpV^6$6>no5r;Cf@c9=k*76WOZ?e5w0R@Cuk85of8!_u_XX-`V?m zZKuOoidDke1&%E2ER9V!3t2r;B$(UoUMd-Ath_g08OC2Orm0NKfe9c=9Eg?@u$)ezgiq9h4uJq9@CS zQvH9DwNA_ttrm%kSycMFKnxqvDTch`O7ti75AS!vve5lO))s+VbXG-nV7=MQ292@X zOU8R*&pm-XK;vWc`=7WsUm71vJs9BuY7uhaI8&`Q5X02kNw2Z?8?2t!+HWiQ9A~-< z2Qc9oj_}0?C_mOyXZl#y@{rvO${3B3Mm5&+aZszmSXow_sygRf#$mq@Vk4RoRf%zL zr@;o7J{w?KX>H)m+7HvNOU1m4p*8I*1>Ug-#XM@~#x56Wtz*6Wg9d}G_dDmCm?xp- zi|GzRm026$7(>1aHWlKXRiEN{xwt_jy+h7##!jEv zdVk}jR7_iaiH?XjL2T(i(ea%QD_zyrqW=f)INM@6f%p&FAImV#O3@$RiO-3&PyTDL z;w-hVv;m%@wlE!cRss0fv?zU>co1do9lYl30@$o==vmje_~7jL%oE9z-5ywZ@um|u zE6>|GsVlb+q3o)MG^}FGvxecrE0<4e>)DtUExl!O(~XoWbn9IJ39h+tmdPSHU!Q%j6v~Ghv-h1=7+cUWC6s(N> z%FZF`Bv+7+LifE7Ehr56O~QbGK@T%g=uu-fkEn@-PxbKpt3hUF4$jGvb3W(e=a>X8 z?;poG;cMW+dh~>+bzq^?!Y_ijNpTty`#R_#MM&P<9tYZopV3h#8GlY;2 zo*vch-uvwzL-PHdv@WN6Z z?lbm*Can|Cj#hJ&MUvx`aCT1eGLfiEDQ}><97Yv9nF=mwD zz!x~{an|Cj#hJ&M&lr=QC1eW5B4eRp>i779?VjKOq=n1Uu*+cz7v#C~r(B@t20JH6 zd*Nj}@x18`d+bqrN4;sX(2|xQGdCcX?}jG(fKNhi8S-YISkOaMDWK_0-z!0*nh6?J z)N6fJj4Gf>$#5i#D;+nBZH`UiDTlG}YtcAki@neHcm{m!>;#6(BN*{nCCMlFIeK7L z(bK4B0?%pqs}Kis@B8*r{0{h_6L}U|@>P0uGa)BLH;*UDz;n=tu~oBs$#KTN+rwe{`GI%kvD>0#h-tpO%1Ps^ zFuE4#;W3G?LOd0zYbRM6#88bNeEPzCy?%%-)C{p9O(3ZZ^Rx?d^}n)L^k~Yp0lmhC z@$x%&du(ODnNB&JlOZIhMCrG`0nK5^7B`(87~|@|5uf^FdqI9m+<5emvVCK;lLV>$-keWw>ywC`tYEw}e}-A{Y@VUA%YnI>q#-fz12cv!$R*a0?Q7Mt z<|MJYta(q&{&YQs9X2SibxD!|SAZQuebowVE&Y=9tDBHYRAlZmQ%Wt+19oHh3P=#y;TEyBV&q|(|d{uiX*?hxM zZqu!hFWdG=9i#>2CoGZq6*Ru>$-yal#MlkQ=*bY)0*6!yFC)S&b;0<-jRSi9ukF|M zFr|RK;_UGZ5fBzl&}Vs1!TJ&f()yi%Ic&~5GTAnMux>~<#4l3?5=s~LsO;dke8{@| z(eaFwWkpf*8+Z;O{xlRhwI(QnNHw8Iw z;4x%cj6!l{#E+3EaUA9U6!6;yA=me|G0ls$-l@~P?>VOJpVj?SW1{z3$JUOk1nPAQ zc^80+l=mva3k0=tRWkfjW4rJ-ADy>KwO3zyKR-NM)Cg+vubAbCiFb^HRmBp^5=5qk zLuJEG;d4J7^G^(5*OVasIOffQt@lCnN zxt?Z^`IQ}|=Sn9oU-uoSvV;@hBdfCRb*347JY6AIHIi1-MiXDiPe%{jfbvr|!56s& z-bX8>_iQEBc;Fag4pA9Uu@U`{Ae3Y5heIdAs&RLD-}fvOJ_M!rdE5e`NR2zG&rJs@ zufwjdizj5G7=v1lW8D$lsUZ^(_ZovIG4(>S^$S_QO&h4!>4M2Rc#P9I;U{Qco&esF z5ruhy=)VkT^@zi?-Bm&Y6Kt>UDd`~#_~ZkWJJU_V>Emyfju(ytbi*#kPB9qQ9efhtNAK}z!xo+CoIOe=C?u4hC{6vb-8pkcCMImsxuhN z%p7DwuiML{Cw@|f7|X(=(8!C52AN=r^-0?T?1ZFob(Ei9w`UzAS+TQOPpS08GM!M0 z(vtT{8(?YZlfCw=LCpm`Rh9PWxr7rDIGRubY}!Hy{CSz&=O# zAZB3{lh#k=WHZg`!%Sc&d@7r)pUOrXT}RFIX(7?JoqI}TXU`T*Rd>PaO}jWDtw_8y z&#!lYCetr6mJG~8j8+Ab)oi8Te&>Dj+*4JZ!I|8fK`y4eWVTp{QA}FVVwP!68f1G9 z+jPaGiPqgo+p(aoeS^TfsRqPr!_==|1z%J+G&>BQ?Ea%{?1b0Q`Bgx#?~+M(MbDy) zuL9cmvnA9VhxUaz6vmi7CVJ?HWs`>W3YZQ7}2F;b7^iXeHY1! z#K>UXQi(}q5og293;C$$N>qF~T%Z$i4LoB!RK1tEdQ24?Oy;gjV5YOmxF>;H<{i8K zC{Hc#6Ele=(ZLueuG;}3M;~Bj- zO(2jdE2;_ynf_#O4UO$*%tn+=6Zje6L53hkIwSLCSeJ_tAx-lB;cK?5j?z&<@_xYe zz%gPz8?ikq;)MEk4MseT8Ch1Vg~#XRpcbS1&Y>{{nDbgm@2{OkaCx#&Qaam1vlvj% zu}}+)W1C7}^+V7dpG6*QEEw+N8V%Le`0V%+-tx+8B$K65?=VW~S$T2|r8niCZ1{nfjoK`BFCG zxpw9RJWnQC-wKC5XvR~M^T?IB)JAx|8n8m6 z3-E~lU^tzr81pVlRlu{Ai?iWP(N2%}Q-(ut4*L8HgxT=d&xY0_xu1J!k8H!N*MeE) zO(oC3zZPE`p$zHma3bX_a7EZ`h`5tnt60gVoZMfGW@^3Nh3TT*x*EyDp#g3)GYBF$GHAvgJZ15TXijo%l zo>ScddcsI+M{gJ=QR};&_6DAs%xfdPVV;aQ7Z&|NwH(!V_d1Hjg}{dP$1HzB#AjGB9D3_e#7j6= zyvF}$WO(3%Mm=3)1Lc{@(tVx>h4A@Lc7fuYE}eQnK7+sEHnfR)bl$)yXSj@FN`3gh z2QvINw3TT(B9qQ=Xz~E0Mkmwy7hpnb9Xd;O$hd)@g9509`NZ@qd-(h>b}N*yUZTYK z2$wDcCH~*!%YWudJ=!zliuM3QbEGw2Dy?x2yn7Zsc^~CFx(<6sN$XkKx=7m&%Cv2N zQQGywsOP(t=l|_r+{19jz4N@@Aj8ha%2h{@R3t-N(i%v<)mL#o{P4@?oW|du|Mp=f zI9!5N+;i1DqDst+xy}9@Y!PrZN}7Eg=bYo2AhFRkCC1W@yV;5-@Y($dxTe|{aPd{M zJsHvgUomVCq)a!f$TZG8D)YM)d6PIX77@a#stpn+YE6`UHi zm$fMVe$4xRK0w!PoJ(g5+iPbi-uHZ}NwG$I25a4y>sW=k!=dHu@ik^?y2dD;ymZLn6-6;Cv9+o4X zok3}V-&XqI6~*a z)K8@I!f%w1dHq}_FW1vz@Atlr;@^|#kk@ZQ8;u*5QPP}6=O%i(~Q8Y&?@lG`qTNTzPJs5uxL8I zR+Z8#)KQw(jp%dKobtf`6|ZT!%XqCZcGIYHwU@RIa0+1gl&ZU7+mhRXJB}6AWqK*h z0#`z5>%z`HO6MuMKG1D+sU`Cr9=z zHka}qrUj7(uKkGIie!e=`Dk9q6Y^c=H9)g~yfu&X-ctAN_leT=?9KQqRetFe{WCJF@teUo@atk~{^f6^-01V4 z$mqL~>kmggU9MbjW=7tPJ|AFCTq-&D(v=nEvY5l<9%dD;Y&cdZC8n|qkp(YZGNT{v zU9WCqEPu(olzC01-uzFQ*Rbo@kU}Gw-|*y1&RBYNIrCbrlV)B^TTe5u^&?wE>#8G| zv$4p$#x^Rs*L2tSl>Tyb?zNk*$i0>hi>?b_9Kl9fB0aR8W)ewwG6qqS*c%O>`X{ouWlyD#Ws>jPQB^M z_Ppr7+;#)n{$tKHv>frorAp2-tgKv5bDj~%v`ab9{yhb1`fGO69XWwI+7h}?FYeq{ zk;$=I3|4OQ^K!T-#-ko7;|e?9v{2$>DQExTEbR-MG+3XG zeN)JGv0m*~HFMaBtahb}&a<@4efc_MF)_zd?9-45?cmvkl1=&gw`bMJV?g;dBU8O8 z-4UbYUt6@EV%*tlTOWfR^>$ca=Ma%Vq$k$Lv^di^m#x&+r&&+3(O*tY<6=<7tU!AK z&}b$!LZh}wYUV=3%A`50mgi;t%ykx;{or{yPRWR-ZeT51*Z-Wo37#h8x#Ov3Kwc3R z*W?)?CYKM`+1?X;qXU>a71)(ZJ8AYiz-F|_sM73IxBX|{OYdPpjj70j7B`dPVYSfA zcY0*Ldk0uDIpDWSl5NUlH>W$)E^c#71Es?A@^R!;(=??^EYZ1GM8vYw*@kp!JsaC- zlXf|gSar+FbW&jJd&6nO?^pHZy&DwiK&1pQQz1K+7P&Cz84JwFg*j8Cd1FU%Ve&K= zrk=`;|LJ1f*9mdwwynArHeJR=iHc1O!v4J{5 zJ$Nfek34VchD!7zqfmP189GuZXU2efhL0%+y>f<*m@&1?1VSk%vd9Z~ya;cXahqaX zYmgJwu#A@b)fw;?vZ4~{L7Eknjmg_UeKy*-<2Nbmg|wfwfel(VP_B)rp92h3&JJbA#&CH@Bq(y;s&n`)+&P8?Zb6pZ8Yjg^}LE-1L9hTk)fMD+j&x3*VJ}g&ieZV%ju$ zlS_Uk7KxX&%kQ1(*iApj%e&c@^=YJFrh@tF*rQ6hF2ZrfiMVn`crFb*mnq&Mg5wHl zZn%h+3U<+*0hHUqp|eACF_*jAHyZQP;ImBd*~(FTM*8;Ds=)1h+iS?oxgs?^Rn{J&_*Q>8&?y`-A#LGLEW{ZdI=dy|CeLxp`l1G{qBmEe*1qJQ8l4|?7EEY z5=gw)|EZV$eD?BtJKn#jyq_x+_%A=7rNnOiboT~ieArgWHO4f2aQgDwNqAe+|JZIi z>Q5iM{5)NG{s1!Oj2^)+oORbB1KTA@5e{jUQY-(Z)P6aBaf*^Z`M-9+W)kDhJym%E z8I+g6Ynt0x(eJ#6antO{>ejdAc_sRt$c}v15!s5-WGf*P-j=ULzU0NHkI1+F?ub15 zkt1>mj&kHrPDFhwm+mCvrVuZNrpl@z<9Frkr$gDXI9t37Kv?r5R z{SO~>c}q+i3tgU`&NZbW3&^%rTvJSAN+j zp#ztDH&w~-_fure(WWdoYlUP6;ZP;o63HH_ZcIO|-ojY&9B2Hn zKcI~VLr=;a>dH8{FQ_&YVLeNoLv!ck^qiqP3kbKFZHRGY<13XrAN8m=o5XO4J3yr* z)wqu9iU_P-{*P3jw9@MxzeYQ0M8fo zD=?Dv-}n_~zsn4Rh@eG%J#eCf!$g?}CnzeJ{Df#gK@Z=jzoj-# z1i%~|{w*RFv#KtJu9N?KMV#SQ_?(+IVzye0xWqe?1>S=Q$)!u~uW#4FV}gBo^nYep zy87;Tz|I_Eau<1-x2f-O1~Nad#Mu5$i2CVOdi5o*=wx-E_rS!+(Kwm6tVi%9bj zd|Ep7=yvS3*p9vQ|M=z={NEf+_OT}~m%A+^b)60w`m*5zj0dFCfE2cJh}xv`b9=24 zi&zh+#@RwP;>~ggwgtn5x7uz0r@L>DkFvP;o@Xz~CM+>r)PSf9A`Q0~!bMOh+1$8F zz)KG*y18x0LN04|gQ2gj8wiTldZ1oPd+3q2dWu>V6g=2U14>WnskY&wMT@7g#e$1H zCrE&hAbG#vndjM^ENk2I$NSGa`AlZMGryVn&2N5ld1mH$7W*Y4``z~AxXbg|@yYVd z{=OXScwNVxTrqxYyX~cx5@)xgZaeCk_zfW!z9IAn+Nt*J4DaZn*Ka`IHj%U8#k!{`&*mWNXs2f_SH<6~t$1UU=mBfcm=B^JUk!j|~ia zjlHQRpnling_f1|*P$1=+E!MNueodZnu6>PjlAb;j=gHkc)pA`dIEv*Wg82Iw!ipD z`ULLiQhQh8*H?nObJ5p&&qaE6z45{$V^PLI=-rSnUV*-kg={;q7LmW(Fy(|9a=drx z8{=z?QNKI>BHz-R!v6DOOB%jp^LxHeJ%#tjSo8Q@>lS%t=Pr2&UzFN_UG?qT=bmkr zHzBXBL7zV_o*r3JfE7q~$u9YZo*jE*lgl2xZhTpayw##pr-0i2{3w(9ILhM4l3MaG zP6RJ6Il=efMqBjIG{-eHm?<`VaSq>XduoO(Wp0Uj572P{`^Tfkl|4FYcv&jT!82u& zw2?2)y@Ry&=kY~!oHA~k(}6PWB_p@@jdL7H4;t82cHva`(NP>vhL@>5W^lmwkQ{5a zU4yZEeaV$2qfyhX-QsE9W?)UX%u%O|qHX>)F1)j~r*m}6`hxt=uV@*B^PMYOw)I3# zZ|`aO9Q(C)o<8%|g?$J{Kie}UqV1K_BC_q|-Umfn0p6>~ZrgHlZ*bem77e!mdo}C@ zHZ*Ji?`_c1mm$4|TY$Y9_5vFkHh}l~wDgOSUc)WGUJZMJ4GkN>drP(S`ADzf7GST2 zy}*Ws4dA`Awe-12ui+M8uZF$AhK3E`y*Fs-JxH(N7GST2y}*Ws4dA`kYUwkPUc)WG zUJZMJ4GkN>doR<{3#8X@3$RziUSRB2#oF5tnb10%!+UtHK}~t<)U`HGkF68>xShI) zQ^H+hY{lWXY|UR#G~TiYoLb9a_Ty^hjoq4UY8 z6JG+_fSsIc+is5v_Z>KscraSE?7^sindtmeq%?Z_?T1g^amTK)Ud759$=9xFtIY&qE^?Mh8u@wdWU<^EbjV~|`>h3) zCkyQ?8E?cza5vTQ9&XAE{DZA0zYstw!-)G>fO{wpp$7CEmCEVY{{(U{p`gtyO)uHWY#I^22^IX1Y zt|*PpbYs^TH7~k#@R`VE5qzByZ+4Zs+I-Q)?#1}EC+|te65P-*a(DZp3*Gr%FY+1G z6}gsNetKYIr??C|>9{|FRygfy^GyEnsR8!au-okZ(4FV{2)6;;Z=G`6j2?IA$R67% zcLzdjN7~*x<#8Lpo*wswqix=(+t`qQZ1|7b43svuFn4zY&WNv_IpRb2l#HXeMda9r z96ddbPNX@VAH``>kAq*50$2M^xy@Ld(;<|xV@q;(gQAn}li+YI?sTNIwRA-W;d}bC z79D4MX0@?J$F|4Y+u6?ccHnJ~Or+b0Th7C= z+3c>PFXPKIHed9pJFCr}XSueMM{Q_TyXdiBU{5sgW=MWC11*IXFWUPTt^v?9-3z-q zYDYu|-F|i3i0F_zo{YLLdkPlc>FS%~tM{q+%>3xQ!_rcvLrKAMC zIzMU?;Lg}_a+%|;w!f;#i$p&&H&Y{AJC^{@?M6BW(&60-d=1e| zC)03T=uhuq8J{nT+A>hiX#;+qsIoVZE4ZI~P_96EdOG%!%MO5|Bp*Fq^>BQ#d?s!n zMpKNZq-=w8?1;Zr6k=A!>G8FQpLMPsH$&{fIc!Ha+B2(-t?6!G9QCHK^$JrC9H87- zHsmCNyBU*$FUAckVeByUKR0fhqP3?DIl#2e18DPUBP2z7EUj1TUy!;)%|>wd-`1(0 zbU%C2=|K4z)FY0=qH{e)aQo!a&d43b(IG<$qk}8aYep4E2VGtq&GeT>#h486%5~?{ z1x2U6a5$hvwu5)$cX{$`uMhX1v^$l*v@4Q{+i(+JKWWQoI%&@s)%N=Erjq=qTbQ&7 z;mf`xeDjxt9~E~*Q!=t}-t7cuS2UGIQ?4kDzKxqWw}yCb?u(8XvF89s;sFP6YhI2# zknqCSk24Hoa-s0VwR`s2S6<$E(vHy${JQnAJ-8e7U9<>u)6g%~?G1k^1~1?K3tO1& z<&v#DyX)pxh;Yh`vF$;8MU3tDVAu7puyrRKCrV*!PMzKL#mfvEg*z6OUOd?K%a?&1 z4|WZF1)AV|u56j$XiFa!)WFuwQgqW0p`gZ-zTp#54GQe zn^0UMv|=8pD0vKgQn2Gd%Cex+NQ#yeN*Jx zL=Wred-9U7-zEv$*Do!2wGBQa248+~(0dJC&7s#$R@^%HgVN~U>k6@IDU2?@4dZkv z?oV`PVMajR*vICeJ#w7~5R>m}YruaiT(m8Cqu>oO*3~AmZQKKxYuOK_F2iq zPX*pNx*B(3938f8ZrrV#_-U~43Y_vkf_EvfC(w<1)u*@grWB|28q-q#rD@o%lMY7! z-z<3>r;vC;#5=S){hsrGk6w)BDgKC(b=&rQ{+oyxBPQ(m{H@4icwQJPpBui9??25y z@MuB(2e0<5Iequ`w@-N-m{q!SF@|OK*w0+qWA7@6y3jL+&d3pnmDqzH@IN zWvWd1Cw#3nwYM0z#$POUeqhX=ILvnN#p3mC#_T!Kw0U^y?f6!K`vWohhb8mzwbv`Q ztMwZ-+{tIDe}1iJEk=g?&etN}!Ypm1P2hPH-Xt{KYj96!dC5ZgCBu#bGx65^N5@Cu zmr)0?9nL#ScJ#EK7USm~*ayD8f;;D}J;q4e#u<{U!1)AkKV*6fAi)DI>OB8_oVhr?MeOoD{fbhy>|w_kW>&IVEaM74f~H- zC}*wwW|FtZ_AlhVG&*EndhdYKxPgy0aLP8ox2ta6)A>S#vR5^`&~4T1`X1XR){M8M z7ygZQn-?9hi0N^z+0k$ut3!KwkE7?q{E^U)f@pd==E?K9J@(J@@fOhV1qIPG!@lv( zk}EMI+OYq+ulr6@l7BsqFYcbUZ?gBMeV*!`gAxmh9pExuYRZyBZ=sAkA$o<}OB z9|!TaB-5l?d@ihnG>zFKaI@2Xu(H^I|8Nm?#rDkGxQUDR5H6NRhZXL6bvE8m$UslB zpGxh`7@XQ`@3fuFD%e=CzD=BoRsq>72JIUJ?E^*x$A)JH|eszquFP!FTq=!PBHQLft->TN{*R*=Hj_O z_NA8md(Xq@Gx?pbM~+=p8ohGC?pKX5{4(UlbM5$|95|o11_0YGTokQG;W{ z(ogl>4D1&*? z^!b~Qi!ra3eDC;w;CAh6`FXhOKDx&^e{JE8{M;Vn^jz?8OA$G7BPMo%ujndXEZ&5zpBFJf=<&XV1)Djk~M4L%k^mZ#CL(E@g~0Ogl` z$ddc{i+7suxQv3_AMJAXrkuu`51@tSeD&BcJK7383%+B+OQLBd?&F(H?fb*9*5e%c z$lK40s*kfxnfI|_?Rdt)?>Kilds64(%d0gh^Nj6j*!k){_n$qE1p~HspL6$K1Whx3 z`#KCe5KCk3&*GQyFdB>OtJ+syV~iho#F%KS8H%|y)$Y3P?WNx@aNxbazRC77tTuMr zJR?h9{6!|e;Ew%x?v;wpm*n@{gS*AfERQko#b23BX4tiD$DTurd^TBKUci?3+`=?X!DfwdsobFota-I>T=6@qa=HK8h+oKzb-90 z?|%a~Ja@kM3#?muL&*OMlyEaj$bHSovA5fD9PRgRzpSIM=2%v0hZ}c{`_7$^xA2Cv zkIoujBPJM6iYFW&iq5+8S6pW=8_<#N34rE(Ni(9Y7AH5Nv-rG$yMleW5A1$$X9o5f z@$Ev$C$imMV?1wrI>lpu%6LL?ZEvrv$sT@HR%My!9A~D&Z&}CE{WpG_$x7$^l5`nb zI@}`JIdI;<1;c9w)MRDN-#&P_7?%QWuQ=}px8%vS`z5?9F2>pa@DhHDsBc{7M=snO zbnT9;7vcd}OE#T5*KHeCdNc0LPB?JoLZqBD>gofFU6Z$rKX+j0BEw@mZ@+%a%{bS4 z!gv}d<$aFpjHd@;zsUB4{i(7t!-KEW^%>8*5Xz7a8FD~MsjS@5_UD>Pyc>9PnG@f# z5N+?E+^uW)jh}OcXwzWdxy_Q&QBvJ5t`C$rg9r_Y4VQa3v%HLxfA^jAk$tjVjO5q(P8=UK z&N%SBl9Z0Gj2m>I=eTP-Lh*JR-XM2>uiMyADc^5NYu{LWitoU>(KE7t+YXxXzd8QY z8(CLn=6X6W6I;%Z*Al!-B7_4Wb`cSL&xHDz)^1F-O?-j-)4`j-$*5f0f-LC!#kHc1 zeTRLBZ;kYwo8LENLducU`F|D%vgXxnM_O=--!D%?i}BkfnOE=0%G^yEDf+xVab4Q{ z55%qAlLbq%9k{M+F({15L&txPl%DP^Gi5u{kYYN@Nkz;M{L+H6WC+^EjqicUGsd=y z$1nZE?zTL8$*Kv?;W^c=F|fQll>+Nrb=B+m&X*XClZ=~rlJRdi$-o_^1RC63I)5o$ zaQE~xeGlUHwlwK;{k63X>EimTbWz>VaFZuHxB2?!v7T8Ty6K{#yip4SRk{!tpeKb$ z4X^MdnA`+2Z&8T|)K`l|-bJFmyk6u^%9}i8>a-iD&+rx$78RF}iFjCfMP-%0nqk@X zO|`XS5eNUg`szS^AiSF4i^><#`G0B_m)r;ItX(p@Mb9XGCi+gm8M99j2IQ&ts<{fm~@?R~LO%-UFXZ0W~^`H$^v zzWSBRix&USpWZ(}Z`xi^KwqI)O4LHDNX&40yS_{Y}>;Wva> z@=eh%d6I!@5kH370m@v>v#$*{02fOFP}P`EY6HnszZ<+NGu~gG*au+8|uoX46LC(ylk{ z2Dr4FOuGdx?N-xngG;;1w0q#v?l)~aT-qb1?SM;r!nB=mX}e7;9!C9PU8c>1OPgg{ z4_w-8)8@jZoo?EExU_RkyBIF*Qqz{frL8e-5H4-AX(MoH*PC_&T-r^h-2#_(t7*5v zrQK!PJ#cCFo3M~IvobQ^HyC^^Eb}yDgw2uqPeevawRBunbZpLNq?7s>9J|9As1FO9%LxD{ z^%gn~Cn1vGO2=^3!EqSF@!!C+S^q-tfeYab2*Y&`JhqKtkwRV#2k8tWg$x@`1yZ#b zr@a&NSgIE7w09vy7=w)KGlmSXXIzyr$QW#7rXbhRV!(i}A_)ANUKbe3F=o5%88;2M zdBD6OB+XAThJcqT!tPRmHZ0Rp;&8TmrW-}-0i+Ns$+%o@*^J(df#BMp5Mhn-V6Zk& zSso5F)C-}3oJvNcFdOBa_0_LJShfZI|24&61AIox{FJgAT*w?eNL@07?STyUK&chX zi#bK$dNW+!j7;z2#>2LOslbW!#9SM)mFZ86ABwQW3`e{NF7hjQ+*oT%q+?t&>;%wF zkaTWu#!&C$j#lSdV~wrF?#=LwHfffEW}2kQEKrdVM`1=5D7=q5TT?FKftr38b_3F_ zlIh&2&^lWyG9~Zih4C)C5LDkp-iYz0xX42My-DK9?-ay0BfbiY)PjuB1sP8c@Mdfp zfO5WNd({4jW4-g?l!sE+xmweZmq~vVj8Tm#lXXVxB{IoE++)bM8+7vj&%@9VMcb+dVPj89asahtZZ1~Zs2sd z^D{;#;lChbI_MJ1XWHqIugfFEIHZLPAY8C;Y4v3}q@6NSh@U~=l6H%cq^wKJVOwrN z+Rht>MA6B0yFI~{x3y3%C_@#PA`FkL^2~&jlH~76$&mOitWM9XwnqtKtM*OBPX&=38 z$}EWdYSE#mfd{Dz)03*gC2i?J+MgorvonOa9sU9i0LCM>_4bDy4>{MRw5G15I!c;u z&@7G7JZgKyzTWY$^P!Y=sjYaKsefN$|8!u^S$vZacfrpw@Nu($GW@3q=TOab#Jhm$ zx9~n-mxkW~wsej3?FsQmfHO7v6I#43D-UQkBYh|0KZC!310)7!CHsO5){i{sX^7jA z=IG7wGKfFZuujkR5SZmIApYy1<5>1(I-FP*^=Ky2HhYD56#k+Ncfmt)oV}DU>PZb~ z9R=7+fSwehF6(1;xs;xHZvy@8h3MPx7oxvB{3T-{Y4?HFRb(B|>H$iLl zHR3%Q*5$*zJ(vjhA-)EFeLRr5kGKiN*8F76GZ>AT&P-c{_*VE4iuQ|-UBwxm7|jXL zY?3q{$iKf%lV|dP?_7wl!f)X{z*WH1U&fD~BgA0%E&XNNGJHD1vmtZ#wM*N!NRIDT zUCQQSBLwM+5_t8Pc{%0@@dEtG`kuwdHqgwJd8m1Aw3+rZgrAjZvy2*;PTLws$br)3#ikoLk7 ztY=gi-ehHv&;6i#42x!#r`8T!^Q^sO?Z7;{K)VC9qav!LAo+8rui)G5ApU|dmE^0h4cNC)C?NBm#lFU%NG*nfN}#!As#_keDu zUx=@%GQM<8Kz^p65uXI@xEO76T_bH7X!n5jAF1bKpgjTFe?->1Ks&VhAEP}6+I-Ls zSNz80NB$VM3~_tl*Vknne;7Anxzc~EeUQ$Yf7hlUs$V~6UJIdnOF8b1X@mD>yo^ElINtG>wvG1o+YC3UAW2I?FzWbfW{RPkT(956tx+ z%0gSm2SfBPt7%nhA@%a|v z=tmDHeTG{MI>!TOZ%N08>3Cn&+nnR)1E5_DTCNAZ8IGdIlZ=1Vt7k!12D*Gn_qX$G z2kjQnGM(hV)uy$ldhTc0-JshAI+vt#pgu}J7`_ML81j&wIZv1PmyKB z*AUG2S%l+JTdrl*e#E77GyB1YL70Onzku*gXYHuRj8(+G3<#^GpP!qj|O81>^G$AP<|KP z6y@j6n}|sN{ScipUbYZ^`l$jtejLc1H;R<>)LYVQgB?SS%Z)4TS;la=A<4{z_)z}G zznswOx^Q^~+;F3EYb;;b-y9Y>-dk_U@izymnng}yLlu4iOXR5k6`_#GscfjL^Mmc2 zDt|@Oa$k94dHr%f!W9fQRn(W)#W7A@8?3nUii$@6Dht&H>iw3#x)EtC0A?(2Z9}DE zr#u{P3{*6Q;~Ar%@aiD&KWeT5A-c2_sZ0}rUcy?2{exyCEa-x3;4*#+5aXDZhRs4V z0hVD{N{jpmEYMaZYJ{l%MwhxzIt;zy1TsB=&8#g>0Ml6I-ULiP>3H6_9zS*2ZPL)O z=w`#u{BjuxLprWIEWqrU)MOsBLs zwuqI6biYqC}Hn8Pq)Gp8+MW45f)gIqR0O>5bJUPM; z&s#)h9OIue{Z`bhs|`6;Ti7aV8v@W4K`Xoobk|z|u0^*;^E3MUpc_n&X)HRj%(k`6 zPeIpi0k{?&T}_R|=8=ZjhJuG6oO=bVZzgOSte)S(IfhuH6>Q}PvM)7uv(zaOMPfHg zrasfy%@U}$3M*+-KNZ##83Fcq?=s`rJL1M3(_$57m$lI2@eraJyTBq`Gj=%x!~^UC z3pvf$w$&-@GphBI z3RdNHV?AYI*-r8wLsb0S1nh}b!!7y$so5TsI7#-p~l zwhZ}aJkO_;QT*peEUfAu(fB9*i3H64qKsR-ZF%8Z?Gx{Cir@Sgja$4E^T+AkHY-rk zmst?{c_`*r^yDWTu>$SlD7+U?pH8?|dvqt%uUVr%VI_rY@jD@*e6u@(!YxiEq379; zGK${^A{JKiKW0Is*XJCoJf8h1qtcI#$rt(<^T+w)S&&ZuUlf8g2I`D8U2ND;`8l{) zlt#t7G|Z$&Vx3CG^Xy0&l|B-&Fh&RzK+HC$eq{k~&@l7c0<4Uxe^IOsZd?_&;^Ot; z8I&@ryv;Ehx0o37$LVGboFmeV_M|xVE+W&#st$D1I-*@^Fi< z#r*O7Tplw!NZ=mCrvdX^%F6HPsCYb+AJZ`9v;MmN@y}|Q@y8-oyy9nWOuyWsDhWS4 zuTn;)L_+t$-yep!pIUW*sYWedF(K41k^Q=c1Q~#Jq z8n<{N3H<~v;-pdZH8`))ajusB2T9WNd`G8`X!JixLeDcDo&HUY{*@&3Jgd>^_iLEs zJcH5W4{Mn5JcH5WKTE`Gt$2q#XZ;M=gCI)d*T^8VHI9!0=K@bRk^=m9_7q#G**qUFPf%*L`3p2lMkvKi^4y``eev28azw$gm8C70x zY}uc@{duOK(=XHLznvt1o-63|>oxkPlhE^QL8srL(La-fp63ZVeWymR?+IA-9Yj9EVhxM;_=RkX%yZN?vFb(oS~I(=?l*hlu_-!RO9E0B=kHd z(CMc{ENqkOqpg1@J_S4Jg-p35Ul@uz*haA1pWw^UB;5f z+;7I|sSiA}P{t6ifS&JnbRxi_pZ;Jxp8V|5^pELzmZ6N2U#*52&od1@ev5_~&$A6Z zp6_fa&7xQ7ZiPMll8S*0@gy+TKz;{5IxOK|(V}ZSx--erb8t^Z{pAC2v z;uiwX!uXnN##aDuMC2+HuOP;F|8*0GfImg~6HNR7u%6#WU~B&?6XPfE^y%q$0N0_s zGSq|o?M_I42pC^ki`Dm!z;}WlK5~-&FTi)y#N$sTq)&0;-7>5{IgXP)19)N{&PkwX z#8&{{iTOKf#(RL5;CalF??m8JcplF&<8K1qTcqU0^z(uB`uc$HgFLPFssp~GP~GJq zeG~9Vl+Psv@i&6!bcIti z@i&1FGcgS7_s_szEWw@_Fyns!{KJKD`925y9`>g#{eBJjBRn5l^7t9>MCjK9Gd=Gb zTK6EB-*17-F<<4I@$Uia^*ae1Y*Bma?0?feh%>O%>K&s_W)b_-Gginu>#oLYNdCG`+@I+ys_mb%WDNbfby;U zz5{&y9LA~mO~7^NT+__{_#ElA@?Ho2tGOOz`TKys4SmZt)4v0Jd39WVhk?ClKP&$~ z1MBkY2Hsd1?;kcW_8YCdD}Z-GpT?N^Uk$u(y;VP_mWa4)O{`DKLSr*6Cc0-2l&%sbzhY6 zXMpwgw5MS_zWD>V{C9zWrRDz|u%7?V67cVU z_4YantdAGR66kw?%jc?ltt{V(j&=(Au)-{VFfjM$l)gB{XyB`t$Mq!-nD4oIK+pbL z2y7XScXt8n<4uhgPkDY5SRZdU0CSJS(uaQq{)W~cUIN|?c|zT!KI{Qr?TwHBzXE=5 z3fdoeus**7{7r>U`EH-eUI*;(c&;D^WuwMRT;53xC1My6M6L1S; z6*2K_;QeSHR9Cjo*MJXc`dSTKToa#<>w)$BTY)(r(=h+<0DEtX&u9O_^i}co!HV*N68k=YfAb!pZz^V0=Y32L1r!3)`OcdkI)C@2v!U1eoW&s(l@TdnxZC zJu%at1-8!nsDJ6$EBL+E{v&|({PPm3_7pbrCgYWy^7@#Kel zA)kUjmzn;%!0)0z4>$2v;ECG!`R`hK%KKg5yD|SxH|Y-p$Del`;t#;xh@+wYodwp% zvtHnj(4WDAl#c^~4#(QZAx2Q}+WIjM_?H^LCBXbXk;hEG0QmVkps&zF)^92BdGq}! zVn48+AMa-V731$&GyMa=`h5Keu-+ce0Poetr&odTRqfb%dN1(M7R3+8hl9Y^Y4X9> zd((G;8T#tXJ-5u;9*!>-D~2B!20vfEMWcl zsu-C2sg}Mj0v@P6|5gHD4|%ql`PBpK>&veL>+<1!&R>HTU0(A0EU*{jM~;bK2DXd` zp0|MY`SmxzdVU?it5F}md&>6v3|Q|!HY}|7V!c&`ycq8W*3*vy-d>~bkTZT9@JATT zEd8FGKtB(7mS4RWK>EeNPRM_ung2fl|5bZlTE_I6KHLZF$9mP0*Z%>Y2y8vCi_u{* zx=Q$bm7&SL8h?4v7Ydg*hJ8U?i&VZ!+$gPV42Qx^)z$F&eDe!$^(~xt+wDFdKvjcp zd2K^Qd9AN1+|U^El{YmD+}RA)`osRJoExW2o|K%($Isi~I%i|~Y9H=*Hm(-(R;I72 zsjhA{l4!`s58?D9?SI|19QQ~AVX$U8fx2K*qaRp#eDXGFuo0JE$$zjZ9D;*upSAva zcve-%qAF_3>sN+yrcIkPS$y5!*x;A`DdPT+Kim`qt~ECy z5|BkX=gw92Pz^BZTve?yst)>a-E<{u8uT^QOFu;dsybxcP}xZORrfdI zg97y3UtYTsE+Wcn8Bkm4tK^MTAMXN#KL+3;Y^Z#>9@J333fZm1)mc_uWlWF1uCj&& z&=Xv(JarALm@$Ho9X;fUZm`i$9SG)5&6zqWZ;A+k<;vRfP$*E%q@jw&mCP#?t_n0r zx3RL0m4t}lLFLM8y7xnC8|o?;P)U!EG&xOGfmNZvWM61yAn1cX z*N1DqydWK@4vUH)?l*&~Hc+v=vN8`orS8RxilFW69t^UW^O*|glguGT@kSEKn@leI zRRdH5os5h!&}vnR4p`}5kTqD!agX5&$qn3$=6g1sn#`AVKk`? z`jIhvoGbttRaNJi!cifKxy&%LW_N0+S3N&OLEy?ZqWt&C4A^c}fyv3(m_#H?LG4Q3>TgJP^!r+!@0JUZk z^VOPlxP&n8M#L&@va~~v!%Po($HsQfL-DbN2ropy>B^OreSZ77osg|Qyzsxaj`V`}8#zIQ7@?cpOg3baRHglA# zh1x)!>@Uo^zA99$wAd^k-IT0WRaI59vsSRK)~Hg~gleeKM_5Y;bHe7@gLUCFC>g|X zT&b-B%<}sUKa-{*lxiTy1vPERw5rW30?W-oEhL32)s}C_P;n_fq^?8ffMd?gJ|$<0 z&K!)?a!3wD<{)9o6=QByh*h-$;)15yN%rH4&bnd#4AjBpt1UkKNK$S^Aj~1RI?!BI z9SUe!)z|4Lmhn`LBo;^+n4*W!0c!oKJucyEQXXQ14fjt)GmryQ8*60?aW#Tf2A39i z*#`OC-&h{R&~LFDs)m}Z^rQDwVE{pDnSH`&Vg@VOv1%mJhjlfg$3sI{2a;!om@7}9 zxF#=5lDdemlY;34xrMO7yCn}3!*)OZjvD)lKvYS?vhnTghtEq-^s#0qP zMAfRb2nIiEP04izOEjw&U#6P@{d)oe*{XqHEf>;e*%){lp==V$x1=yO$(}$lV5GD1 z?w=KUZG4ze!jS_OrbkQP4I)?7@p(lm6EsAw!pSj*P;+F7D_ePp=0 z`2JS1qH@g@vid?-tXPha;f634Lh%8TvXt+sF=MVLv`OvDW0|XD@Dp2sX-Q*E z&y|H$NGvc9rRZ~s)&DD3tn}d-Z#mLnF_9?6SU#cEp>RNI(WN=(B`Z&^sGDld*+V_e zY4b-vQBImFKj{|d8qcL_8D>7*aT$O@RIidMfyHzzfa^W~eMy->rR9SK)`;?vR~2C@ z4xeYy>8zEs8h%11y`?x(0m3zCteS>eYb-W1h^MurSr=MvEtoh!313V(s6+Fvkw9dCd{PERMY_ zSAI`V4&_Np=JXmepPZ?Ja1VgCz^Oi;}cNg1CTEy`;6>bs>aoFp0%_q z);XjeF;vZe7?RLr=*W4gZ;7S0 x!CHP?lEEZAovTNu*hUEoyp(K)`J`^n7ud}4bC%Oa`Eql@R+E!lo)k!`{|l=Uzaszu diff --git a/simulators/ovp/test1/application/application.c b/simulators/ovp/test1/application/application.c deleted file mode 100644 index faec3ae5..00000000 --- a/simulators/ovp/test1/application/application.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -int foo = 0x37; -int bar = 34; - -int main() { - long i; - printf("\nHello\n\n"); - - for (i=0; i<50000; i++) { - printf("%d\n", i); - foo = 0x37; - printf("foo: (0x%x) = 0x%x\n", &foo, foo); - bar = 34; - printf("bar: (0x%x) = %d\n\n", &bar, bar); - } - - return 0; -} diff --git a/simulators/ovp/test1/platform/beforeInstruction.cpp b/simulators/ovp/test1/platform/beforeInstruction.cpp deleted file mode 100644 index 2f30f082..00000000 --- a/simulators/ovp/test1/platform/beforeInstruction.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "beforeInstruction.hpp" - -Uns8 bpCount; -Addr breakpoints[255]; - -//Ignore warning: deprecated conversion from string constant to ‘char*’ -#pragma GCC diagnostic ignored "-Wwrite-strings" - -void printArmCortexM3Registers(icmProcessorObject processor) { - Uns32 registers[17]; - icmPrintf("---------------\t\t---------------\n"); - readRegister(processor, "R0", registers[0]); - readRegister(processor, "R1", registers[1]); - readRegister(processor, "R2", registers[2]); - readRegister(processor, "R3", registers[3]); - readRegister(processor, "R4", registers[4]); - readRegister(processor, "R5", registers[5]); - readRegister(processor, "R6", registers[6]); - readRegister(processor, "R7", registers[7]); - readRegister(processor, "R8", registers[8]); - readRegister(processor, "R9", registers[9]); - readRegister(processor, "R10", registers[10]); - readRegister(processor, "R11", registers[11]); - readRegister(processor, "R12", registers[12]); - readRegister(processor, "SP", registers[13]); - readRegister(processor, "LR", registers[14]); - readRegister(processor, "PC", registers[15]); - readRegister(processor, "CPSR", registers[16]); - icmPrintf("R0: 0x%08x\t\t", registers[0]); - icmPrintf("R1: 0x%08x\n", registers[1]); - icmPrintf("R2: 0x%08x\t\t", registers[2]); - icmPrintf("R3: 0x%08x\n", registers[3]); - icmPrintf("R4: 0x%08x\t\t", registers[4]); - icmPrintf("R5: 0x%08x\n", registers[5]); - icmPrintf("R6: 0x%08x\t\t", registers[6]); - icmPrintf("R7: 0x%08x\n", registers[7]); - icmPrintf("R8: 0x%08x\t\t", registers[8]); - icmPrintf("R9: 0x%08x\n", registers[9]); - icmPrintf("R10: 0x%08x\t\t", registers[10]); - icmPrintf("R11: 0x%08x\n", registers[11]); - icmPrintf("R12: 0x%08x\n\n", registers[12]); - icmPrintf("SP: 0x%08x\t\t", registers[13]); - icmPrintf("LR: 0x%08x\n", registers[14]); - icmPrintf("PC: 0x%08x\n", registers[15]); - icmPrintf("PSR: 0x%08x\n\n", registers[16]); -} - -Bool readRegister(icmProcessorObject processor, char *regName, Uns32 &value) { - if (regName[0] == 'P' && regName[1] == 'C') { - value = (Uns32)processor.getPC(); - return True; - } else { - return processor.readReg(regName, &value); - } -} - -Bool writeRegister(icmProcessorObject processor, char *regName, Uns32 &newValue) { - if (regName[0] == 'P' && regName[1] == 'C') { - processor.setPC((Addr)newValue); - return True; - } else { - return processor.writeReg(regName, &newValue); - } -} - - -void addBreakpoint(Addr breakAddr) { - if (breakAddr != 0x00 && bpCount != 255) { - breakpoints[bpCount] = breakAddr; - bpCount++; - } -} - -Addr simulateUntilBP(icmProcessorObject processor) { - if (bpCount == 0) { - icmPlatform::Instance()->simulate(); - return 0x00; - } - - Addr currentPC = 0x00; - while (processor.simulate(1) == ICM_SR_SCHED) { - currentPC = processor.getPC(); - for (Uns8 u = 0; u < bpCount; u++) { - if (currentPC == breakpoints[u]) { - return currentPC; - } - } - } - - return 0x00; -} diff --git a/simulators/ovp/test1/platform/beforeInstruction.hpp b/simulators/ovp/test1/platform/beforeInstruction.hpp deleted file mode 100644 index 85c7c5b9..00000000 --- a/simulators/ovp/test1/platform/beforeInstruction.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef BEFORE_INSTRUCTION_HPP -#define BEFORE_INSTRUCTION_HPP - -#include "icm/icmCpuManager.hpp" - -using namespace icmCpuManager; - -/** - * Prints all the registers for an ARM Cortex M3 processor. - * @param processor The processor (must be an ARM Cortex M3) - */ -void printArmCortexM3Registers(icmProcessorObject processor); - -/** - * Reads a register and stores its content in an Uns32 variable. - * @param processor The processor for which to read the register - * @param regName The name of the register as a string - * @param value The address of where to store the register's content - */ -Bool readRegister(icmProcessorObject processor, char *regName, Uns32 &value); - -/** - * Writes the value given as an Uns32 variable to a register. - * @param processor The processor for which to write the variable - * @param regName The name of the register as a string - * @param newValue The address of the new value to be written to the register - */ -Bool writeRegister(icmProcessorObject processor, char *regName, Uns32 &newValue); - - -/** - * Adds a breakpoint for simulateUntilBreakpoint - * @param breakAddr The address to be added as a breakpoint - */ -void addBreakpoint(Addr breakAddr); - -/** - * Simulates until breakpoint, - * or the entire application file at once if no breakpoint was added. - * Returns the address of the next instruction, - * or zero if simulation did not stop at a breakpoint. - * @param processor The processor to run the simulation on - */ -Addr simulateUntilBP(icmProcessorObject processor); - -#endif \ No newline at end of file diff --git a/simulators/ovp/test1/platform/flakyMemory.cpp b/simulators/ovp/test1/platform/flakyMemory.cpp deleted file mode 100644 index ccef766d..00000000 --- a/simulators/ovp/test1/platform/flakyMemory.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "flakyMemory.hpp" - - -void createFlakyMem( - icmProcessorObject processor, - Addr lowAddr, - Addr highAddr, - const char *vlnvRoot -) { - - icmBusObject *mainBus; - icmBusObject *interBus; - icmBusObject *mmcBus; - icmMmcObject *mmc1; - icmMemoryObject *memory1; - icmMemoryObject *memory2; - icmMemoryObject *memory3; - -#if 0 - // get location of mmc object file: - const char *flakyMem = icmGetVlnvString( - vlnvRoot, - "ovpworld.org", - "mmc", - "flakyMemory", - "1.0", - "model" - ); -#endif - // create full MMC - mmc1 = new icmMmcObject("mmc1", "/srv/scratch/sirozipp/build/lib/libflaky.so", "modelAttrs", 0, False); - - // create the processor bus - mainBus = new icmBusObject("bus1", 32); - - // create the intermediate bus - interBus = new icmBusObject("bus2", 32); - - // create the bus connecting the mmc to the memory - mmcBus = new icmBusObject("bus3", 32); - - // connect mmc direct to processor ports - processor.connect(*mainBus, *mainBus); - - // connect master port of MMC to bus - mmc1->connect(*interBus, "sp1", False); - mmc1->connect(*mmcBus, "mp1", True); - - if (lowAddr != 0x00) { - memory1 = new icmMemoryObject("mem1", ICM_PRIV_RWX, lowAddr-1); - memory1->connect("memp1", *mainBus, 0x00); - } - memory2 = new icmMemoryObject("mem2", ICM_PRIV_RWX, highAddr-lowAddr); - memory2->connect("memp2", *mmcBus, lowAddr); - if (highAddr != 0xffffffff) { - memory3 = new icmMemoryObject("mem3", ICM_PRIV_RWX, 0xffffffff-(highAddr+1)); - memory3->connect("memp3", *mainBus, highAddr+1); - } - - mainBus->newBridge(*interBus, "br1", "sp2", "mp2", lowAddr, highAddr, lowAddr); - - // show the bus connections - mainBus->printConnections(); - interBus->printConnections(); - mmcBus->printConnections(); -} diff --git a/simulators/ovp/test1/platform/flakyMemory.hpp b/simulators/ovp/test1/platform/flakyMemory.hpp deleted file mode 100644 index a39ca709..00000000 --- a/simulators/ovp/test1/platform/flakyMemory.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FLAKY_MEMORY_HPP -#define FLAKY_MEMORY_HPP - -#include "icm/icmCpuManager.hpp" - -using namespace icmCpuManager; - -/** Creates flaky memory by attaching an MMC for the specified address range. - * @param processor The processor on which to set up the MMC - * @param loAddr The lowest address for which to do on-the-fly manipulation. - * @param hiAddr The highest address for which to do manipulation. - */ -void createFlakyMem( - icmProcessorObject processor, - Addr loAddr, - Addr hiAddr, - const char *vlnvRoot = 0 -); - - -#endif \ No newline at end of file diff --git a/simulators/ovp/test1/platform/platform.cpp b/simulators/ovp/test1/platform/platform.cpp deleted file mode 100644 index 4934a2d2..00000000 --- a/simulators/ovp/test1/platform/platform.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include - -#include "icm/icmCpuManager.hpp" -#include "flakyMemory.hpp" -#include "beforeInstruction.hpp" - -// enable relaxed scheduling for maximum performance -#define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED) - - -icmProcessorObject createPlatform( - const char *application, - bool gdb, - bool flaky=false, - Addr lowAddr=0x00, - Addr highAddr=0xffffffff -) { - // select library components - const char *vlnvRoot = 0; // when null use default library - const char *vlnvRoot2 ="/srv/scratch/sirozipp/build/lib/" ; - const char *model = icmGetVlnvString(vlnvRoot, - "arm.ovpworld.org", - "processor", - "armm", - "1.0", - "model"); - const char *semihosting = icmGetVlnvString(vlnvRoot, "arm.ovpworld.org", "semihosting", "armNewlib", "1.0", "model"); - - // set attributes for CPU model - icmAttrListObject icmAttr; - icmAttr.addAttr("endian", "little"); - icmAttr.addAttr("compatibility", "nopBKPT"); - icmAttr.addAttr("variant", "Cortex-M3"); - icmAttr.addAttr("UAL", "1"); - - icmProcessorObject processor( - "cpu-Cortex-M3", // CPU name - "armm", // CPU type - 0, // CPU cpuId - 0, // CPU model flags - 32, // address bits - model, // model file - "modelAttrs", // morpher attributes - gdb?ICM_ATTR_DEFAULT:SIM_ATTRS, // simulation attributes - &icmAttr, // user-defined attributes - semihosting, // semi-hosting file - "modelAttrs" // semi-hosting attributes - ); - -// if (flaky) { - createFlakyMem(processor, lowAddr, highAddr, vlnvRoot2); - // } - - if (gdb) { - processor.debugThisProcessor(); - } - - // load the processor object file - processor.loadLocalMemory(application, true, true, true); - - return processor; -} - - -// Main simulation routine -int main(int argc, char ** argv) { - const char *application = "application.elf"; - bool gdb = false; - Uns32 portNum = (Uns32)-1; - - if(argc >= 2) { - application = argv[1]; - if(argc >= 3) { - gdb = true; - portNum = (Uns32)atoi(argv[2]); - } - } - - icmPlatform platform( - "fiPlatformCpp", - ICM_VERBOSE | ICM_STOP_ON_CTRLC, - gdb ? "rsp" : 0, - gdb ? portNum : 0 - ); - icmProcessorObject processor = createPlatform(application, gdb); - - simulateUntilBP(processor); - - return 0; -} diff --git a/src/core/config/CMakeLists.txt b/src/core/config/CMakeLists.txt index 9327469c..4ee279f9 100644 --- a/src/core/config/CMakeLists.txt +++ b/src/core/config/CMakeLists.txt @@ -1,4 +1,4 @@ -#### Configuration file emitting BUILD_OVP/BOCHS defines #### +#### Configuration file emitting BUILD_BOCHS/GEM5/... defines #### configure_file(${CMAKE_CURRENT_SOURCE_DIR}/VariantConfig.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/VariantConfig.hpp) diff --git a/src/core/config/VariantConfig.hpp.in b/src/core/config/VariantConfig.hpp.in index 9b819df5..607d5b29 100644 --- a/src/core/config/VariantConfig.hpp.in +++ b/src/core/config/VariantConfig.hpp.in @@ -3,7 +3,6 @@ #cmakedefine BUILD_BOCHS #cmakedefine BUILD_GEM5 -#cmakedefine BUILD_OVP #cmakedefine BUILD_QEMU #cmakedefine BUILD_T32 #cmakedefine T32_MOCK_API diff --git a/src/core/sal/CMakeLists.txt b/src/core/sal/CMakeLists.txt index 7b2a7284..4a947a1c 100644 --- a/src/core/sal/CMakeLists.txt +++ b/src/core/sal/CMakeLists.txt @@ -27,17 +27,6 @@ elseif(BUILD_GEM5) gem5/Gem5ArmCPU.cc ) endif(BUILD_ARM) -elseif(BUILD_OVP) - set(SRCS - CPU.cc - CPUState.cc - Listener.cc - ListenerManager.cc - SALConfig.cc - Register.cc - SimulatorController.cc - ${VARIANT}/OVPController.cc - ) elseif(BUILD_QEMU) set(SRCS CPU.cc diff --git a/src/core/sal/ConcreteCPU.hpp b/src/core/sal/ConcreteCPU.hpp index c77c6b32..f7d40c6d 100644 --- a/src/core/sal/ConcreteCPU.hpp +++ b/src/core/sal/ConcreteCPU.hpp @@ -9,8 +9,6 @@ #else #error Active config currently not supported! #endif -#elif defined BUILD_OVP - #include "ovp/OVPConfig.hpp" #elif defined BUILD_QEMU #include "qemu/QEMUConfig.hpp" #elif defined BUILD_T32 diff --git a/src/core/sal/SALConfig.cc b/src/core/sal/SALConfig.cc index cdb65c59..29354f1f 100644 --- a/src/core/sal/SALConfig.cc +++ b/src/core/sal/SALConfig.cc @@ -5,8 +5,7 @@ namespace fail { // Flag initialization depends on the current selected simulator // (For now, the initialization values are all the same): #if defined BUILD_BOCHS || defined BUILD_GEM5 || \ - defined BUILD_OVP || defined BUILD_QEMU || \ - defined BUILD_T32 + defined BUILD_T32 || defined BUILD_QEMU const address_t ADDR_INV = static_cast (0); const address_t ANY_ADDR = static_cast (-1); const unsigned ANY_INSTR = static_cast (-1); diff --git a/src/core/sal/SALConfig.hpp b/src/core/sal/SALConfig.hpp index ff364ae2..23ef54d9 100644 --- a/src/core/sal/SALConfig.hpp +++ b/src/core/sal/SALConfig.hpp @@ -10,8 +10,6 @@ #include "bochs/BochsConfig.hpp" #elif defined BUILD_GEM5 #include "gem5/Gem5Config.hpp" -#elif defined BUILD_OVP - #include "ovp/OVPConfig.hpp" #elif defined BUILD_QEMU #include "qemu/QEMUConfig.hpp" #elif defined BUILD_T32 diff --git a/src/core/sal/SALInst.hpp b/src/core/sal/SALInst.hpp index 974c5835..464e663a 100644 --- a/src/core/sal/SALInst.hpp +++ b/src/core/sal/SALInst.hpp @@ -20,14 +20,6 @@ namespace fail { typedef Gem5Controller ConcreteSimulatorController; //!< concrete simulator (type) } -#elif defined BUILD_OVP - -#include "ovp/OVPController.hpp" - -namespace fail { -typedef OVPController ConcreteSimulatorController; //!< concrete simulator (type) -} - #elif defined BUILD_QEMU #include "qemu/QEMUController.hpp" diff --git a/src/core/sal/ovp/FailOVPInit.ah b/src/core/sal/ovp/FailOVPInit.ah deleted file mode 100644 index fe7ed613..00000000 --- a/src/core/sal/ovp/FailOVPInit.ah +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __OVPINIT_AH__ - #define __OVPINIT_AH__ - -#include "config/VariantConfig.hpp" - -#ifdef BUILD_OVP - -#include - -#include "../SALInst.hpp" - -aspect FailOVPInit { - advice call("% ...::startSimulation(...)") : before () - { - std::cout << "OVP init aspect!" << std::endl; - // TODO: Log-Level? - // TODO pass on command-line parameters - fail::simulator.startup(); - } -}; - -#endif // BUILD_OVP -#endif // __OVPINIT_AH__ diff --git a/src/core/sal/ovp/OVPConfig.hpp b/src/core/sal/ovp/OVPConfig.hpp deleted file mode 100644 index f664af56..00000000 --- a/src/core/sal/ovp/OVPConfig.hpp +++ /dev/null @@ -1,20 +0,0 @@ -/** - * \brief Type definitions and configuration settings for - * the OVP simulator. - */ - -#ifndef __OVP_CONFIG_HPP__ - #define __OVP_CONFIG_HPP__ - -#include - -namespace fail { - -typedef uint32_t guest_address_t; //!< the guest memory address type -typedef uint8_t* host_address_t; //!< the host memory address type -typedef uint32_t register_data_t; //!< register data type (32 bit) -typedef int timer_t; //!< type of timer IDs - -} // end-of-namespace: fail - -#endif // __OVP_CONFIG_HPP__ diff --git a/src/core/sal/ovp/OVPController.cc b/src/core/sal/ovp/OVPController.cc deleted file mode 100644 index eeea2036..00000000 --- a/src/core/sal/ovp/OVPController.cc +++ /dev/null @@ -1,132 +0,0 @@ -#include - -#include "OVPController.hpp" -#include "OVPMemory.hpp" -#include "OVPRegister.hpp" -#include "ovp/OVPStatusRegister.hpp" - -namespace fail { - -OVPController::OVPController() - : SimulatorController(new OVPRegisterManager(), new OVPMemoryManager()) -{ - // FIXME: This should be obsolete now... -// set = new UniformRegisterSet(RT_GP); -// setStatus = new UniformRegisterSet(RT_ST); -// setPC = new UniformRegisterSet(RT_PC); -} - -OVPController::~OVPController() -{ - // FIXME: This should be obsolete now... -// delete set; -// delete setStatus; -// delete setPC; - - // Free memory of OVPRegister objects (actually allocated in make*Register): - for (RegisterManager::iterator it = m_Regs->begin(); it != m_Regs->end(); it++) - delete (*it); // free the memory, allocated in the constructor -} - -void OVPController::makeGPRegister(int width, void *link, const string& name) -{ - // Add general purpose register - OVPRegister *reg = new OVPRegister(m_currentRegId++, width, link, RT_GP); - reg->setName(name); - m_Regs->add(reg); - // Note: The RegisterManager (aka m_Regs) automatically assigns the - // added registers (herein typed OVPRegister) to their matching - // UniformRegisterSet (@see RegisterManager::add). -} - - -void OVPController::makeSTRegister(Register *reg, const string& name) -{ - // Add status register - reg->setName(name); - cerr << "Add Status Register: " << reg << endl; - m_Regs->add(reg); -} - -void OVPController::makePCRegister(int width, void *link, const string& name) -{ - // Add general purpose register - OVPRegister *reg = new OVPRegister(m_currentRegId++, width, link, RT_PC); - reg->setName(name); - m_Regs->add(reg); -} - -// FIXME: This should be obsolete now... -/* -void OVPController::finishedRegisterCreation() -{ - m_Regs->add(*set); - m_Regs->add(*setStatus); - m_Regs->add(*setPC); -} -*/ - -void OVPController::onInstrPtrChanged(address_t instrPtr) -{ - // make some funny outputs - unsigned int r0 = m_Regs->getSetOfType(RT_GP)->getRegister(0)->getData(); - OVPRegisterManager *ovp_Regs = (OVPRegisterManager*) m_Regs; - // FIXME: This cast seems to be invalid: RT_GP vs. OVPStatusRegister (= RT_ST)? - OVPStatusRegister *rid_st = (OVPStatusRegister*) m_Regs->getSetOfType(RT_GP)->first(); -// cerr << "Addr: " << rid_st << endl; - unsigned int st = rid_st->getData(); - -// save("/srv/scratch/sirozipp/test.txt"); - -// ovpplatform.setPC(0x123); - -// restore("/srv/scratch/sirozipp/test.txt"); -// cerr << "instrPtr: 0x" << hex << instrPtr << " SP: 0x" << hex << m_Regs->getStackPointer() \ -// << " R0: 0x" << hex << r0 << " ST: 0x" << hex << st << endl; - - // Check for active breakpoint-Listeners: - ListenerManager::iterator it = m_EvList.begin(); - while (it != m_EvList.end()) { - // FIXME: Performance verbessern (dazu muss entsprechend auch die Speicherung - // in ListenerManager(.cc|.hpp) angepasst bzw. verbessert werden). - BPSingleListener* pEvBreakpt = dynamic_cast(*it); - if (pEvBreakpt && (instrPtr == pEvBreakpt->getWatchInstructionPointer() || - pEvBreakpt->getWatchInstructionPointer() == ANY_ADDR)) { - pEvBreakpt->setTriggerInstructionPointer(instrPtr); - it = m_EvList.makeActive(it); - // "it" has already been set to the next element (by calling - // makeActive()): - continue; // -> skip iterator increment - } - BPRangeListener* pEvRange = dynamic_cast(*it); - if (pEvRange && pEvRange->isMatching(instrPtr)) { - pEvBreakpt->setTriggerInstructionPointer(instrPtr); - it = m_EvList.makeActive(it); - continue; // dito. - } - it++; - } - m_EvList.fireActiveListeners(); -} - -bool OVPController::save(const string& path) -{ - // TODO! - ovpplatform.save(path); - return false; // TODO -} - -void OVPController::restore(const string& path) -{ - //TODO! - assert(path.length() > 0 && - "FATAL ERROR: Tried to restore state without valid path!"); - ovpplatform.restore(path); -} - -void OVPController::reboot() -{ - // TODO! -} - -} // end-of-namespace: fail diff --git a/src/core/sal/ovp/OVPController.hpp b/src/core/sal/ovp/OVPController.hpp deleted file mode 100644 index 36641b94..00000000 --- a/src/core/sal/ovp/OVPController.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef __OVP_CONTROLLER_HPP__ - #define __OVP_CONTROLLER_HPP__ - -#include -#include -#include -#include - -#include "../SimulatorController.hpp" -#include "../Listener.hpp" -#include "../Register.hpp" -#include "ovp/OVPPlatform.hpp" - -namespace fail { - -extern OVPPlatform ovpplatform; - -/** - * \class OVPController - * OVP-specific implementation of a SimulatorController. - */ -class OVPController : public SimulatorController { -private: - // FIXME: This should be obsolete now... -// UniformRegisterSet *set; //(RT_GP); -// UniformRegisterSet *setStatus;//(RT_ST); -// UniformRegisterSet *setPC;//(RT_PC); - - // FIXME: Perhaps this should be declared as a static member: - unsigned int m_currentRegId; - // NOTE: Constants (such as GPRegisterId in sal/x86/Architecture.hpp) - // are much easier to read... -public: - /** - * Initialize the controller. - */ - OVPController(); - ~OVPController(); - void onInstrPtrChanged(address_t instrPtr); - /** - * Save simulator state. - * @param path Location to store state information - * @return \c true if the state has been successfully saved, \c false otherwise - */ - bool save(const std::string& path); - /** - * Restore simulator state. - * @param path Location to previously saved state information - */ - void restore(const std::string& path); - /** - * Reboot simulator. - */ - void reboot(); - /** - * Returns the current instruction pointer. - * @return the current eip - */ - void makeGPRegister(int, void*, const std::string&); - void makeSTRegister(Register *, const std::string&); - void makePCRegister(int, void*, const std::string&); - /** - * Due to empty RegisterSets are not allowed, OVP platform - * must tell OVPController when it is finished - * - * FIXME: This should be obsolete now... - */ -// void finishedRegisterCreation(); -}; - -} // end-of-namespace: fail - -#endif // __OVP_CONTROLLER_HPP__ diff --git a/src/core/sal/ovp/OVPMemory.hpp b/src/core/sal/ovp/OVPMemory.hpp deleted file mode 100644 index ffce66de..00000000 --- a/src/core/sal/ovp/OVPMemory.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef __OVP_MEMORY_HPP__ - #define __OVP_MEMORY_HPP__ - -#include "../Memory.hpp" - -namespace fail { - -/** - * \class OVPMemoryManager - * Represents a concrete implemenation of the abstract - * MemoryManager to provide access to OVP's memory pool. - */ -class OVPMemoryManager : public MemoryManager { -public: - /** - * Constructs a new MemoryManager object and initializes - * it's attributes appropriately. - */ - OVPMemoryManager() : MemoryManager() { } - /** - * Retrieves the size of the available simulated memory. - * @return the size of the memory pool in bytes - */ - size_t getPoolSize() const { return 0; } - /** - * Retrieves the starting address of the host memory. This is the - * first valid address in memory. - * @return the starting address - */ - host_address_t getStartAddr() const { return 0; } - /** - * Retrieves the byte at address \a addr in the memory. - * @param addr The guest address where the byte is located. - * The address is expected to be valid. - * @return the byte at \a addr - */ - byte_t getByte(guest_address_t addr) { return 0; } - /** - * Retrieves \a cnt bytes at address \a addr in the memory. - * @param addr The guest address where the bytes are located. - * The address is expected to be valid. - * @param cnt the number of bytes to be retrieved. \a addr + \a cnt - * is expected to not exceed the memory limit. - * @param dest Pointer to destination buffer to copy the data to. - */ - void getBytes(guest_address_t addr, size_t cnt, void *dest) { } - /** - * Writes the byte \a data to memory. - * @param addr The guest address to write. - * The address is expected to be valid. - * @param data The new byte to write - */ - void setByte(guest_address_t addr, byte_t data) { } - /** - * Copies data to memory. - * @param addr The guest address to write. - * The address is expected to be valid. - * @param cnt The number of bytes to be retrieved. \a addr + \a cnt - * is expected to not exceed the memory limit. - * @param src Pointer to data to be copied. - */ - void setBytes(guest_address_t addr, size_t cnt, void const *src) { } -}; - -} // end-of-namespace: fail - -#endif // __OVP_MEMORY_HPP__ diff --git a/src/core/sal/ovp/OVPRegister.hpp b/src/core/sal/ovp/OVPRegister.hpp deleted file mode 100644 index dd6b3fe0..00000000 --- a/src/core/sal/ovp/OVPRegister.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef __OVP_REGISTER_HPP__ - #define __OVP_REGISTER_HPP__ - -#include "../Register.hpp" -#include "ovp/OVPPlatform.hpp" -//#include "ovp/OVPStatusRegister.hpp" - -extern OVPPlatform ovpplatform; - -namespace fail { - -/** - * \class OVPRegister - * OVP-specific implementation of x86 registers. - */ -class OVPRegister : public Register { -private: - void *reg; -public: - /** - * Constructs a new register object. - * @param id the unique id of this register (simulator specific) - * @param width width of the register (8, 16, 32 or 64 bit should suffice) - * @param link pointer to bochs internal register memory - * @param t type of the register - */ - OVPRegister(unsigned int id, regwidth_t width, void* link, RegisterType t) - : Register(id, t, width) { reg = link; } - /** - * Retrieves the data of the register. - * @return the current register data - */ - regdata_t getData() { return ovpplatform.getRegisterData(reg); } - /** - * Sets the content of the register. - * @param data the new register data to be written - */ - void setData(regdata_t data) { ovpplatform.setRegisterData(reg, data); } -}; - -/** - * \class OVPRegister - * OVP-specific implementation of the RegisterManager. - */ -class OVPRegisterManager : public RegisterManager { -public: - /** - * Returns the current instruction pointer. - * @return the current eip - */ - virtual address_t getInstructionPointer() - { - return ovpplatform.getPC(); - } - /** - * Retruns the top address of the stack. - * @return the starting address of the stack - */ - virtual address_t getStackPointer() - { - return ovpplatform.getSP(); - } - /** - * Retrieves the base ptr (holding the address of the - * current stack frame). - * @return the base pointer - */ - virtual address_t getBasePointer() - { - return 0; - } -}; - -} // end-of-namespace: fail - -#endif // __OVP_REGISTER_HPP__