From 79c8c394bd14fff353300a237f8feaad4722f448 Mon Sep 17 00:00:00 2001 From: Martin Petran Date: Fri, 11 Oct 2024 13:51:21 +0200 Subject: [PATCH] init --- ...-building-plugins-without-an-install.patch | 216 + ...-building-plugins-without-an-install.patch | 216 + ...-building-plugins-without-an-install.patch | 216 + .github/workflows/build.yaml | 65 + .gitignore | 2 + .gitmodules | 3 + CMakeLists.txt | 43 + LICENSE | 49 + README.md | 11 + binaryninjaapi | 1 + disass.c | 408 ++ disass.h | 355 + nec850.cpp | 6386 +++++++++++++++++ nec850.h | 148 + plugin.json | 27 + shell.nix | 8 + 16 files changed, 8154 insertions(+) create mode 100644 .github/workflows/3.5_0001-Support-building-plugins-without-an-install.patch create mode 100644 .github/workflows/4.0_0001-Support-building-plugins-without-an-install.patch create mode 100644 .github/workflows/4.1_0001-Support-building-plugins-without-an-install.patch create mode 100644 .github/workflows/build.yaml create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 160000 binaryninjaapi create mode 100644 disass.c create mode 100644 disass.h create mode 100644 nec850.cpp create mode 100644 nec850.h create mode 100644 plugin.json create mode 100644 shell.nix diff --git a/.github/workflows/3.5_0001-Support-building-plugins-without-an-install.patch b/.github/workflows/3.5_0001-Support-building-plugins-without-an-install.patch new file mode 100644 index 0000000..e4c7c6b --- /dev/null +++ b/.github/workflows/3.5_0001-Support-building-plugins-without-an-install.patch @@ -0,0 +1,216 @@ +From 34e7f0a80b85c4b125ec3a0dc0937606df63335a Mon Sep 17 00:00:00 2001 +From: Glenn Smith +Date: Thu, 4 Apr 2024 21:49:55 -0700 +Subject: [PATCH] Support building plugins without an install + +--- + CMakeLists.txt | 56 ++++++++++++++----- + cmake/generate_stubs.py | 121 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 163 insertions(+), 14 deletions(-) + create mode 100644 cmake/generate_stubs.py + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3fe70f98..d85d2c17 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -23,10 +23,36 @@ add_library(binaryninjaapi STATIC ${BN_API_SOURCES}) + target_include_directories(binaryninjaapi + PUBLIC ${PROJECT_SOURCE_DIR}) + +-find_package(BinaryNinjaCore REQUIRED) +-target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) +-target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) +-target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) ++find_package(BinaryNinjaCore) ++if(BinaryNinjaCore_FOUND) ++ target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) ++ target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) ++ target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) ++else() ++ if(APPLE) ++ target_link_options(binaryninjaapi PUBLIC -undefined dynamic_lookup) ++ elseif(MSVC) ++ # Generate stubs.cpp with implementations of all the BNAPI functions ++ execute_process(COMMAND python ${PROJECT_SOURCE_DIR}/cmake/generate_stubs.py ${PROJECT_SOURCE_DIR}/binaryninjacore.h ${PROJECT_BINARY_DIR}/stubs) ++ ++ # Compile those stubs into a stub library we can use to fool the linker ++ add_library(binaryninjacore_stubs SHARED ${PROJECT_BINARY_DIR}/stubs/stubs.cpp) ++ set_target_properties(binaryninjacore_stubs ++ PROPERTIES OUTPUT_NAME binaryninjacore ++ SOVERSION 1 ++ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ ) ++ target_include_directories(binaryninjacore_stubs PUBLIC ${PROJECT_SOURCE_DIR}) ++ ++ # Be sure to only link against the stubs archive file ++ add_dependencies(binaryninjaapi binaryninjacore_stubs) ++ target_link_libraries(binaryninjaapi PUBLIC "$/$.lib") ++ else() ++ target_link_options(binaryninjaapi PUBLIC "LINKER:--allow-shlib-undefined") ++ endif() ++endif() + + set_target_properties(binaryninjaapi PROPERTIES + CXX_STANDARD 17 +@@ -71,16 +97,18 @@ function(bn_install_plugin target) + list(APPEND CMAKE_MODULE_PATH "${BN_API_SOURCE_DIR}/cmake") + + # BinaryNinjaCore has the user plugins dir define that we want +- find_package(BinaryNinjaCore REQUIRED) +- if(WIN32) +- install(TARGETS ${target} RUNTIME +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) +- +- install(FILES $ +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR} OPTIONAL) +- else() +- install(TARGETS ${target} LIBRARY +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ find_package(BinaryNinjaCore) ++ if(BinaryNinjaCore_FOUND) ++ if(WIN32) ++ install(TARGETS ${target} RUNTIME ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ ++ install(FILES $ ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR} OPTIONAL) ++ else() ++ install(TARGETS ${target} LIBRARY ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ endif() + endif() + endif() + endfunction() +diff --git a/cmake/generate_stubs.py b/cmake/generate_stubs.py +new file mode 100644 +index 00000000..4e062037 +--- /dev/null ++++ b/cmake/generate_stubs.py +@@ -0,0 +1,121 @@ ++# Copyright (c) 2015-2024 Vector 35 Inc ++# ++# Permission is hereby granted, free of charge, to any person obtaining a copy ++# of this software and associated documentation files (the "Software"), to ++# deal in the Software without restriction, including without limitation the ++# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++# sell copies of the Software, and to permit persons to whom the Software is ++# furnished to do so, subject to the following conditions: ++# ++# The above copyright notice and this permission notice shall be included in ++# all copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++# IN THE SOFTWARE. ++ ++# Based on BinExport ++ ++# Copyright 2011-2024 Google LLC ++# ++# 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 ++# ++# https://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. ++ ++import argparse ++import os ++import re ++import sys ++ ++parser = argparse.ArgumentParser(sys.argv[0]) ++parser.add_argument("core_header") ++parser.add_argument("build_dir") ++ ++options = parser.parse_args() ++ ++print(f"GENERATE STUBS: {options.core_header} -> {options.build_dir}") ++print(f"{sys.executable} {' '.join(sys.argv)}") ++ ++os.makedirs(options.build_dir, exist_ok=True) ++output_source = os.path.join(options.build_dir, 'stubs.cpp') ++ ++with open(output_source, 'w') as stubs: ++ stubs.write(""" ++// Copyright (c) 2015-2024 Vector 35 Inc ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy ++// of this software and associated documentation files (the "Software"), to ++// deal in the Software without restriction, including without limitation the ++// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++// sell copies of the Software, and to permit persons to whom the Software is ++// furnished to do so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in ++// all copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++// IN THE SOFTWARE. ++ ++// Based on BinExport ++ ++// Copyright 2011-2024 Google LLC ++// ++// 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 ++// ++// https://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. ++ ++#define BINARYNINJACORE_LIBRARY ++#include "binaryninjacore.h" ++#undef BINARYNINJACORE_LIBRARY ++ ++extern "C" { ++""") ++ ++ with open(options.core_header, 'r') as header: ++ header_conts = header.read() ++ ++ # Quick preprocess of comments in case we have commented defs ++ header_conts = re.sub(r'//.*\n', '\n', header_conts) ++ ++ # Pull out all core api functions to generate stubs ++ for match in re.finditer( ++ r'(?m:)\t(BINARYNINJACOREAPI [^;]*);', ++ header_conts ++ ): ++ group = match.group(1) ++ ++ # Void functions don't have a return (TODO: breaks if we ever return a fn ptr) ++ void_group = re.search(r'(?m:)BINARYNINJACOREAPI\s+void\s+.*', group) ++ if void_group is not None: ++ stubs.write(f'{match.group(1)} {{ }}\n') ++ else: ++ stubs.write(f'{match.group(1)} {{ return {{ }}; }}\n') ++ ++ stubs.write(""" ++} ++ """) +\ No newline at end of file +-- +2.43.3 + diff --git a/.github/workflows/4.0_0001-Support-building-plugins-without-an-install.patch b/.github/workflows/4.0_0001-Support-building-plugins-without-an-install.patch new file mode 100644 index 0000000..53ea71e --- /dev/null +++ b/.github/workflows/4.0_0001-Support-building-plugins-without-an-install.patch @@ -0,0 +1,216 @@ +From 6c9f6915db3d578227194f737728dc3165115d39 Mon Sep 17 00:00:00 2001 +From: Glenn Smith +Date: Thu, 4 Apr 2024 21:49:55 -0700 +Subject: [PATCH 1/1] Support building plugins without an install + +--- + CMakeLists.txt | 56 ++++++++++++++----- + cmake/generate_stubs.py | 121 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 163 insertions(+), 14 deletions(-) + create mode 100644 cmake/generate_stubs.py + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 2c543f85..621ff15e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -30,10 +30,36 @@ add_library(binaryninjaapi STATIC ${BN_API_SOURCES}) + target_include_directories(binaryninjaapi + PUBLIC ${PROJECT_SOURCE_DIR}) + +-find_package(BinaryNinjaCore REQUIRED) +-target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) +-target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) +-target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) ++find_package(BinaryNinjaCore) ++if(BinaryNinjaCore_FOUND) ++ target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) ++ target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) ++ target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) ++else() ++ if(APPLE) ++ target_link_options(binaryninjaapi PUBLIC -undefined dynamic_lookup) ++ elseif(MSVC) ++ # Generate stubs.cpp with implementations of all the BNAPI functions ++ execute_process(COMMAND python ${PROJECT_SOURCE_DIR}/cmake/generate_stubs.py ${PROJECT_SOURCE_DIR}/binaryninjacore.h ${PROJECT_BINARY_DIR}/stubs) ++ ++ # Compile those stubs into a stub library we can use to fool the linker ++ add_library(binaryninjacore_stubs SHARED ${PROJECT_BINARY_DIR}/stubs/stubs.cpp) ++ set_target_properties(binaryninjacore_stubs ++ PROPERTIES OUTPUT_NAME binaryninjacore ++ SOVERSION 1 ++ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ ) ++ target_include_directories(binaryninjacore_stubs PUBLIC ${PROJECT_SOURCE_DIR}) ++ ++ # Be sure to only link against the stubs archive file ++ add_dependencies(binaryninjaapi binaryninjacore_stubs) ++ target_link_libraries(binaryninjaapi PUBLIC "$/$.lib") ++ else() ++ target_link_options(binaryninjaapi PUBLIC "LINKER:--allow-shlib-undefined") ++ endif() ++endif() + + add_subdirectory(vendor/fmt EXCLUDE_FROM_ALL) + set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON) +@@ -87,16 +113,18 @@ function(bn_install_plugin target) + list(APPEND CMAKE_MODULE_PATH "${BN_API_SOURCE_DIR}/cmake") + + # BinaryNinjaCore has the user plugins dir define that we want +- find_package(BinaryNinjaCore REQUIRED) +- if(WIN32) +- install(TARGETS ${target} RUNTIME +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) +- +- install(FILES $ +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR} OPTIONAL) +- else() +- install(TARGETS ${target} LIBRARY +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ find_package(BinaryNinjaCore) ++ if(BinaryNinjaCore_FOUND) ++ if(WIN32) ++ install(TARGETS ${target} RUNTIME ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ ++ install(FILES $ ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR} OPTIONAL) ++ else() ++ install(TARGETS ${target} LIBRARY ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ endif() + endif() + endif() + endfunction() +diff --git a/cmake/generate_stubs.py b/cmake/generate_stubs.py +new file mode 100644 +index 00000000..4e062037 +--- /dev/null ++++ b/cmake/generate_stubs.py +@@ -0,0 +1,121 @@ ++# Copyright (c) 2015-2024 Vector 35 Inc ++# ++# Permission is hereby granted, free of charge, to any person obtaining a copy ++# of this software and associated documentation files (the "Software"), to ++# deal in the Software without restriction, including without limitation the ++# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++# sell copies of the Software, and to permit persons to whom the Software is ++# furnished to do so, subject to the following conditions: ++# ++# The above copyright notice and this permission notice shall be included in ++# all copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++# IN THE SOFTWARE. ++ ++# Based on BinExport ++ ++# Copyright 2011-2024 Google LLC ++# ++# 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 ++# ++# https://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. ++ ++import argparse ++import os ++import re ++import sys ++ ++parser = argparse.ArgumentParser(sys.argv[0]) ++parser.add_argument("core_header") ++parser.add_argument("build_dir") ++ ++options = parser.parse_args() ++ ++print(f"GENERATE STUBS: {options.core_header} -> {options.build_dir}") ++print(f"{sys.executable} {' '.join(sys.argv)}") ++ ++os.makedirs(options.build_dir, exist_ok=True) ++output_source = os.path.join(options.build_dir, 'stubs.cpp') ++ ++with open(output_source, 'w') as stubs: ++ stubs.write(""" ++// Copyright (c) 2015-2024 Vector 35 Inc ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy ++// of this software and associated documentation files (the "Software"), to ++// deal in the Software without restriction, including without limitation the ++// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++// sell copies of the Software, and to permit persons to whom the Software is ++// furnished to do so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in ++// all copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++// IN THE SOFTWARE. ++ ++// Based on BinExport ++ ++// Copyright 2011-2024 Google LLC ++// ++// 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 ++// ++// https://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. ++ ++#define BINARYNINJACORE_LIBRARY ++#include "binaryninjacore.h" ++#undef BINARYNINJACORE_LIBRARY ++ ++extern "C" { ++""") ++ ++ with open(options.core_header, 'r') as header: ++ header_conts = header.read() ++ ++ # Quick preprocess of comments in case we have commented defs ++ header_conts = re.sub(r'//.*\n', '\n', header_conts) ++ ++ # Pull out all core api functions to generate stubs ++ for match in re.finditer( ++ r'(?m:)\t(BINARYNINJACOREAPI [^;]*);', ++ header_conts ++ ): ++ group = match.group(1) ++ ++ # Void functions don't have a return (TODO: breaks if we ever return a fn ptr) ++ void_group = re.search(r'(?m:)BINARYNINJACOREAPI\s+void\s+.*', group) ++ if void_group is not None: ++ stubs.write(f'{match.group(1)} {{ }}\n') ++ else: ++ stubs.write(f'{match.group(1)} {{ return {{ }}; }}\n') ++ ++ stubs.write(""" ++} ++ """) +\ No newline at end of file +-- +2.44.0.windows.1 + diff --git a/.github/workflows/4.1_0001-Support-building-plugins-without-an-install.patch b/.github/workflows/4.1_0001-Support-building-plugins-without-an-install.patch new file mode 100644 index 0000000..96fe152 --- /dev/null +++ b/.github/workflows/4.1_0001-Support-building-plugins-without-an-install.patch @@ -0,0 +1,216 @@ +From 8071d66a654cbbf193b65813ab35d4b894f428b4 Mon Sep 17 00:00:00 2001 +From: Glenn Smith +Date: Thu, 4 Apr 2024 21:49:55 -0700 +Subject: [PATCH] Support building plugins without an install + +--- + CMakeLists.txt | 56 ++++++++++++++----- + cmake/generate_stubs.py | 121 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 163 insertions(+), 14 deletions(-) + create mode 100644 cmake/generate_stubs.py + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 57ed627e..0a434a5d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -33,10 +33,36 @@ add_library(binaryninjaapi STATIC ${BN_API_SOURCES}) + target_include_directories(binaryninjaapi + PUBLIC ${PROJECT_SOURCE_DIR}) + +-find_package(BinaryNinjaCore REQUIRED) +-target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) +-target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) +-target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) ++find_package(BinaryNinjaCore) ++if(BinaryNinjaCore_FOUND) ++ target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) ++ target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) ++ target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) ++else() ++ if(APPLE) ++ target_link_options(binaryninjaapi PUBLIC -undefined dynamic_lookup) ++ elseif(MSVC) ++ # Generate stubs.cpp with implementations of all the BNAPI functions ++ execute_process(COMMAND python ${PROJECT_SOURCE_DIR}/cmake/generate_stubs.py ${PROJECT_SOURCE_DIR}/binaryninjacore.h ${PROJECT_BINARY_DIR}/stubs) ++ ++ # Compile those stubs into a stub library we can use to fool the linker ++ add_library(binaryninjacore_stubs SHARED ${PROJECT_BINARY_DIR}/stubs/stubs.cpp) ++ set_target_properties(binaryninjacore_stubs ++ PROPERTIES OUTPUT_NAME binaryninjacore ++ SOVERSION 1 ++ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs ++ ) ++ target_include_directories(binaryninjacore_stubs PUBLIC ${PROJECT_SOURCE_DIR}) ++ ++ # Be sure to only link against the stubs archive file ++ add_dependencies(binaryninjaapi binaryninjacore_stubs) ++ target_link_libraries(binaryninjaapi PUBLIC "$/$.lib") ++ else() ++ target_link_options(binaryninjaapi PUBLIC "LINKER:--allow-shlib-undefined") ++ endif() ++endif() + + if(BN_REF_COUNT_DEBUG) + target_compile_definitions(binaryninjaapi PUBLIC BN_REF_COUNT_DEBUG) +@@ -94,16 +120,18 @@ function(bn_install_plugin target) + list(APPEND CMAKE_MODULE_PATH "${BN_API_SOURCE_DIR}/cmake") + + # BinaryNinjaCore has the user plugins dir define that we want +- find_package(BinaryNinjaCore REQUIRED) +- if(WIN32) +- install(TARGETS ${target} RUNTIME +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) +- +- install(FILES $ +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR} OPTIONAL) +- else() +- install(TARGETS ${target} LIBRARY +- DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ find_package(BinaryNinjaCore) ++ if(BinaryNinjaCore_FOUND) ++ if(WIN32) ++ install(TARGETS ${target} RUNTIME ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ ++ install(FILES $ ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR} OPTIONAL) ++ else() ++ install(TARGETS ${target} LIBRARY ++ DESTINATION ${BinaryNinjaCore_USER_PLUGINS_DIR}) ++ endif() + endif() + endif() + endfunction() +diff --git a/cmake/generate_stubs.py b/cmake/generate_stubs.py +new file mode 100644 +index 00000000..48ab574f +--- /dev/null ++++ b/cmake/generate_stubs.py +@@ -0,0 +1,121 @@ ++# Copyright (c) 2015-2024 Vector 35 Inc ++# ++# Permission is hereby granted, free of charge, to any person obtaining a copy ++# of this software and associated documentation files (the "Software"), to ++# deal in the Software without restriction, including without limitation the ++# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++# sell copies of the Software, and to permit persons to whom the Software is ++# furnished to do so, subject to the following conditions: ++# ++# The above copyright notice and this permission notice shall be included in ++# all copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++# IN THE SOFTWARE. ++ ++# Based on BinExport ++ ++# Copyright 2011-2024 Google LLC ++# ++# 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 ++# ++# https://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. ++ ++import argparse ++import os ++import re ++import sys ++ ++parser = argparse.ArgumentParser(sys.argv[0]) ++parser.add_argument("core_header") ++parser.add_argument("build_dir") ++ ++options = parser.parse_args() ++ ++print(f"GENERATE STUBS: {options.core_header} -> {options.build_dir}") ++print(f"{sys.executable} {' '.join(sys.argv)}") ++ ++os.makedirs(options.build_dir, exist_ok=True) ++output_source = os.path.join(options.build_dir, 'stubs.cpp') ++ ++with open(output_source, 'w') as stubs: ++ stubs.write(""" ++// Copyright (c) 2015-2024 Vector 35 Inc ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy ++// of this software and associated documentation files (the "Software"), to ++// deal in the Software without restriction, including without limitation the ++// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++// sell copies of the Software, and to permit persons to whom the Software is ++// furnished to do so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in ++// all copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++// IN THE SOFTWARE. ++ ++// Based on BinExport ++ ++// Copyright 2011-2024 Google LLC ++// ++// 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 ++// ++// https://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. ++ ++#define BINARYNINJACORE_LIBRARY ++#include "binaryninjacore.h" ++#undef BINARYNINJACORE_LIBRARY ++ ++extern "C" { ++""") ++ ++ with open(options.core_header, 'r') as header: ++ header_conts = header.read() ++ ++ # Quick preprocess of comments in case we have commented defs ++ header_conts = re.sub(r'//.*\n', '\n', header_conts) ++ ++ # Pull out all core api functions to generate stubs ++ for match in re.finditer( ++ r'(?m:)\t(BINARYNINJACOREAPI [^;]*);', ++ header_conts ++ ): ++ group = match.group(1) ++ ++ # Void functions don't have a return (TODO: breaks if we ever return a fn ptr) ++ void_group = re.search(r'(?m:)BINARYNINJACOREAPI\s+void\s+.*', group) ++ if void_group is not None: ++ stubs.write(f'{match.group(1)} {{ }}\n') ++ else: ++ stubs.write(f'{match.group(1)} {{ return {{ }}; }}\n') ++ ++ stubs.write(""" ++} ++ """) +\ No newline at end of file +-- +2.43.3 + diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..44f9b8b --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,65 @@ +name: Build + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +env: + BUILD_TYPE: RelWithDebInfo + +jobs: + build: + runs-on: ${{matrix.config.os}} + strategy: + matrix: + config: + - { + os: windows-2019, + name: windows + } + - { + os: macos-13, + name: macos + } + - { + os: ubuntu-22.04, + name: ubuntu + } + version: + # These work but are excessive for building + # - v03.02.03814 + # - v3.3.3996 + # - v3.4.4271-stable + - v3.5.4526-stable + - v4.0.4958-stable + - dev + steps: + - uses: actions/checkout@v3 + with: + submodules: 'true' + - uses: seanmiddleditch/gha-setup-ninja@master + - uses: ilammy/msvc-dev-cmd@v1 + - name: Update submodule + run: | + cd binaryninjaapi + git fetch --tags + git checkout --force ${{matrix.version}} + git submodule update --init --recursive + - name: Patch api to allow building headlessly + shell: bash + run: | + cd binaryninjaapi + git apply --verbose ../.github/workflows/4.1_0001-Support-building-plugins-without-an-install.patch \ + || git apply --verbose ../.github/workflows/4.0_0001-Support-building-plugins-without-an-install.patch \ + || git apply --verbose ../.github/workflows/3.5_0001-Support-building-plugins-without-an-install.patch + - name: Configure CMake + run: cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: ${{matrix.config.name}}-${{matrix.version}} + path: ${{github.workspace}}/build/*nec850_arch* diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5acb669 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.vscode diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..94fe504 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "binaryninjaapi"] + path = binaryninjaapi + url = https://github.com/Vector35/binaryninja-api diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..503202f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,43 @@ +# MIT License +# +# Copyright (c) 2015-2024 Vector 35 Inc +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +cmake_minimum_required(VERSION 3.24) +set(CMAKE_OSX_ARCHITECTURES "arm64") +project(nec850_arch CXX C) + +set(CMAKE_CXX_STANDARD 17) + +set(HEADLESS 1) +find_path( + BN_API_PATH + NAMES binaryninjaapi.h + # List of paths to search for the clone of the api + HINTS ../.. binaryninjaapi $ENV{BN_API_PATH} + REQUIRED +) +add_subdirectory(${BN_API_PATH} api) + +add_library(${PROJECT_NAME} SHARED nec850.cpp disass.c ) + +target_link_libraries(${PROJECT_NAME} PUBLIC binaryninjaapi) + +bn_install_plugin(${PROJECT_NAME}) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0d70b83 --- /dev/null +++ b/LICENSE @@ -0,0 +1,49 @@ +MIT License + +Copyright (c) 2015-2024 Vector 35 Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +https://github.com/emesare/setup-binary-ninja + +ISC License + +Copyright 2023 emesare + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +https://github.com/google/binexport + +Copyright 2011-2024 Google LLC + +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 + + https://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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..39beabb --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Renesas NEC850 Architecture Plugin + +This Binary Ninja plugin provides a native implemantion for the Renesas RH850/V850 architectue. The main reason for writing this from scratch instead of using existing plugin is that any Architecture plugin wirtten in Python is not usable for large binaries as the analysis takes ages. Therefore, this is a complete coverage of this architecture wirtten purely in C/C++. + +## Install + +1. Clone this repo: `git clone TODO && cd nec850_arch` +2. Fetch submodules: `git submodule update --init --recursive` +3. CMake things: `mkdir build && cd build && cmake .. -TODO=/opt/binaryninja` (Replace the `/opt/binaryninja` string at the end with an actual install path of your instance) +4. Make things and install plugin: `make -j4 && cp libnec850_arch.so ~/binaryninja/plugins/` (Replace the last part of the command with valid path to the plugins directory for your platform) + diff --git a/binaryninjaapi b/binaryninjaapi new file mode 160000 index 0000000..ab5c0b3 --- /dev/null +++ b/binaryninjaapi @@ -0,0 +1 @@ +Subproject commit ab5c0b34b473fa6cdc5ad55635e670e27688d71c diff --git a/disass.c b/disass.c new file mode 100644 index 0000000..73aa670 --- /dev/null +++ b/disass.c @@ -0,0 +1,408 @@ +#include "disass.h" +#include +#include +#include + +typedef struct { + uint64_t mask; + uint16_t shr; + uint16_t shl; + uint16_t add; + uint16_t size; // in bits + uint16_t sign; // 0 unsigned + uint16_t index; + enum op_type type; +} disass_op_t; + +typedef struct { + const char* name; //instructio name + enum insn_id insn_id; // Instruction ID + uint16_t size; // instruction size + uint64_t mask; // instruction mask + uint64_t static_mask; + uint16_t n; // Number of arguments + enum insn_type op_type; // Type of oepration + enum op_condition cond; // Conditionals + disass_op_t fields[5]; // Operands +} disass_insn_t; + + +const disass_insn_t instruction_list[] = { +// { "name" , enum , size, mask , static_mask , n, op_type , cond , {{field ,shr,shl, +, size, sign, index, TYPE_REG}, ...} + { "trfsr.s" , N850_TRFSR , 4, 0x7E0040E , 0x7E00400 , 1, OP_TYPE_SUB, COND_NV, {{0x0000000E, 1, 0, 0, 3, UNSIGNED, 0, TYPE_IMM}, {0}, {0}, {0}, {0}}}, + { "cvtf.hs" , N850_CVTFHS , 4, 0xFFE2FC42 , 0x7E20442 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.ls" , N850_CVTFLS , 4, 0xF7E1FC42 , 0x7E10442 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf0000000, 28, 0, 0, 4, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.sl" , N850_CVTFSL , 4, 0xFFE4FC44 , 0x7E40444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.sh" , N850_CVTFSH , 4, 0xFFE3FC42 , 0x7E30442 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.sul" , N850_CVTFSUL , 4, 0xFFF4FC44 , 0x07F40444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.suw" , N850_CVTFSUW , 4, 0xFFF4FC40 , 0x07F40440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.sw" , N850_CVTFSW , 4, 0xFFF4FC40 , 0x07F40440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.uls" , N850_CVTFULS , 4, 0xF7F1FC42 , 0x07F10442 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf0000000, 28, 0, 0, 4, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.uws" , N850_CVTFUWS , 4, 0xFFF0FC42 , 0x07F00442 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "cvtf.ws" , N850_CVTFWS , 4, 0xFFE0FC42 , 0x07E00442 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "loop" , N850_LOOP , 4, 0x6FFFFFF , 0x6E00001 , 2, OP_TYPE_LOOP, COND_NZ, {{0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000fffe, 0, 0, 0, 16, UNSIGNED, 1, TYPE_LOOP}, {0}, {0}, {0}}}, + { "rie" , N850_RIE , 2, 0x0040 , 0x0040 , 0, OP_TYPE_CMP, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + + // 6-byte insturctions + { "mov" , N850_MOVI , 6, 0x63fffffffff , 0x62000000000 , 2, OP_TYPE_MOV, COND_NV, {{0xffff0000, 16, 0, 0, 16, UNSIGNED, 0, TYPE_IMM}, {0xffff, 0, 16, 0, 16, UNSIGNED, 0, TYPE_IMM},{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}}}, + { "jr" , N850_JRL , 6, 0x2e0fffeffff , 0x2e000000000 , 1, OP_TYPE_JMP, COND_NV, {{0}, {0xffff0000, 16, 0, 0, 16, UNSIGNED, 0, TYPE_JMP}, {0xffff, 0, 16, 0, 16, UNSIGNED, 0, TYPE_JMP}, {0}, {0}}}, + /*UNTESTED*/{ "jarl" , N850_JARL2 , 6, 0x2fffffeffff , 0x2e000000000 , 2, OP_TYPE_CALL, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xffff0000, 16, 0, 0, 16, UNSIGNED, 0, TYPE_MEM}, {0xffff, 0, 16, 0, 16, UNSIGNED, 0, TYPE_MEM}, {0}, {0}}}, + /*UNTESTED*/{ "ld.b" , N850_LDBL , 6, 0x79FFFF5ffff , 0x78000050000 , 3, OP_TYPE_LOAD, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x7f00000, 20, 0, 0, 7, SIGNED, 0, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 0, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}}}, + { "ld.bu" , N850_LDBUL , 6, 0x7BFFFF5ffff , 0x7A000050000 , 3, OP_TYPE_LOAD, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x7f00000, 20, 0, 0, 7, SIGNED, 0, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 0, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}}}, + { "ld.dw" , N850_LDDW , 6, 0x7BFFFE9ffff , 0x7A000090000 , 3, OP_TYPE_LOAD, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x7e00000, 20, 0, 0, 7, SIGNED, 0, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 0, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}}}, + /*UNTESTED*/{ "ld.h" , N850_LDHL , 6, 0x79FFFE7ffff , 0x78000070000 , 3, OP_TYPE_LOAD, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x7e00000, 20, 0, 0, 7, SIGNED, 0, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 0, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}}}, + { "ld.hu" , N850_LDHUL , 6, 0x7BFFFE7ffff , 0x7A000070000 , 3, OP_TYPE_LOAD, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x7e0000, 20, 0, 0, 7, SIGNED, 0, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 0, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}}}, + { "ld.w" , N850_LDWL , 6, 0x79FFFE9ffff , 0x78000090000 , 3, OP_TYPE_LOAD, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x7e00000, 20, 0, 0, 7, SIGNED, 0, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 0, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}}}, + /*UNTESTED*/{ "st.b" , N850_STDL , 6, 0x79FFFFDffff , 0x780000D0000 , 3, OP_TYPE_STORE, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x7f00000, 20, 0, 0, 7, SIGNED, 1, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 1, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}}}, + { "st.dw" , N850_STDW , 6, 0x7BFFFEfffff , 0x7A0000F0000 , 3, OP_TYPE_STORE, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x7e00000, 20, 0, 0, 7, SIGNED, 1, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 1, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}}}, + { "st.h" , N850_STHL , 6, 0x7BFFFEDffff , 0x7A0000D0000 , 3, OP_TYPE_STORE, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x7e00000, 20, 0, 0, 7, SIGNED, 1, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 1, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}}}, + { "st.w" , N850_STWL , 6, 0x79FFFEFffff , 0x780000F0000 , 3, OP_TYPE_STORE, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x7e00000, 20, 0, 0, 7, SIGNED, 1, TYPE_MEM}, {0xffff, 0, 7, 0, 16, SIGNED, 1, TYPE_MEM}, {0x0000f8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}}}, + { "prepare" , N850_PREPARE , 4, 0x7bfffe1 , 0x7800001 , 2, OP_TYPE_OR, COND_NV, {{0x003e0000, 17, 0, 0, 5, UNSIGNED, 1, TYPE_IMM}, {0x0001ffe0, 4, 0, 0, 12, UNSIGNED, 0, TYPE_LIST}, {0x0010000, 16, 0, 0, 1, UNSIGNED, 0, TYPE_LIST}, {0}, {0}}}, // TODO ???? + + + // 4 byte insturctions + // Floats + /*UNTESTED*/{ "absf.s" , N850_ABSFS , 4, 0xFFE0FC48 , 0x07E00448 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "addf.s" , N850_ADDFS , 4, 0xFFFFFC60 , 0x7E00460 , 3, OP_TYPE_ADD, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "ceilf.sl" , N850_CEILFSL , 4, 0xFFE2F444 , 0x07E20444 , 2, OP_TYPE_MOV, COND_NV, {{0x000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "ceilf.sul" , N850_CEILFSUL , 4, 0xFFF2F444 , 0x07F20444 , 2, OP_TYPE_MOV, COND_NV, {{0x000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "ceilf.suw" , N850_CEILFSUW , 4, 0xFFF2FC40 , 0x07F20440 , 2, OP_TYPE_MOV, COND_NV, {{0x000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "ceilf.sw" , N850_CEILFSW , 4, 0xFFE2FC40 , 0x07E20440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "cmovf.s" , N850_CMOVFS , 4, 0xFFFFFC0E , 0x07E00400 , 4, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 0, TYPE_CCCC}, {0}}}, + { "cmpf.s" , N850_CMPFS , 4, 0xFFFF7C2E , 0x07E00420 , 4, OP_TYPE_CMP, COND_NV, {{0x7800, 11, 0, 0, 4, UNSIGNED, 0, TYPE_COND}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 3, TYPE_IMM}, {0}}}, + /*{ "cmpf.s(F)" , N850_CMPFSF , 4, 0xFFFF042E , 0x07E00420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(UN)" , N850_CMPFSUN , 4, 0xFFFF0C2E , 0x07E00C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(EQ)" , N850_CMPFSEQ , 4, 0xFFFF142E , 0x07E01420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(UEQ)" , N850_CMPFSUEQ , 4, 0xFFFF1C2E , 0x07E01C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(OLT)" , N850_CMPFSOLT , 4, 0xFFFF242E , 0x07E02420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(ULT)" , N850_CMPFSULT , 4, 0xFFFF2C2E , 0x07E02C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(OLE)" , N850_CMPFSOLE , 4, 0xFFFF342E , 0x07E03420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(ULE)" , N850_CMPFSULE , 4, 0xFFFF3C2E , 0x07E03C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(SF)" , N850_CMPFSSF , 4, 0xFFFF442E , 0x07E04420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(NGLE)" , N850_CMPFSNGLE , 4, 0xFFFF4C2E , 0x07E04C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(SEQ)" , N850_CMPFSSEQ , 4, 0xFFFF542E , 0x07E05420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(NGL)" , N850_CMPFSNGL , 4, 0xFFFF5C2E , 0x07E05C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(SLT)" , N850_CMPFSLT , 4, 0xFFFF642E , 0x07E06420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(NGE)" , N850_CMPFSNGE , 4, 0xFFFF6C2E , 0x07E06C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(LE)" , N850_CMPFSLE , 4, 0xFFFF742E , 0x07E07420 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + { "cmpf.s(NGT)" , N850_CMPFSNGT , 4, 0xFFFF7C2E , 0x07E07C20 , 3, OP_TYPE_CMP, COND_NV, {{0}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 2, TYPE_IMM}, {0}}}, + */ + { "divf.s" , N850_DIVFS , 4, 0xFFFFFC6E , 0x7E0046E , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "floorf.sl" , N850_FLOORFSL , 4, 0xFFE3F444 , 0x7E30444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "floorf.sul" , N850_FLOORFSUL , 4, 0xFFF3F444 , 0x7F30444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "floorf.suw" , N850_FLOORFSUW , 4, 0xFFF3FC40 , 0x7F30440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "floorf.sw" , N850_FLOORFSW , 4, 0xFFE3FC40 , 0x7E30440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "fmaf.s" , N850_FMAFS , 4, 0xFFFFFCE0 , 0x7E004E0 , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "fmsf.s" , N850_FMSFS , 4, 0xFFFFFCE2 , 0x7E004E2 , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "fnmaf.s" , N850_FNMAFS , 4, 0xFFFFFCE4 , 0x7E004E4 , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "fnmsf.s" , N850_FNMSFS , 4, 0xFFFFFCE6 , 0x7E004E6 , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "maxf.s" , N850_MAXFS , 4, 0xFFFFFC68 , 0x7E00468 , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "minf.s" , N850_MINFS , 4, 0xFFFFFC6A , 0x7E0046A , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + { "mulf.s" , N850_MULFS , 4, 0xFFFFFC64 , 0x7E00464 , 3, OP_TYPE_DIV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "negf.s" , N850_NEGFS , 4, 0xFFE1FC48 , 0x7E10448 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "recipf.s" , N850_RECIPFS , 4, 0xFFE1FC48 , 0x7E1044E , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "roundf.sl" , N850_ROUNDFSL , 4, 0xFFE0F444 , 0x7E00444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "roundf.sul" , N850_ROUNDFSUL , 4, 0xFFF0F444 , 0x7F00444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "roundf.suw" , N850_ROUNDFSUW , 4, 0xFFF0FC40 , 0x7F00440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "roundf.sw" , N850_ROUNDFSW , 4, 0xFFE0FC40 , 0x7E00440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "rsqrtf.s" , N850_RSQRTFS , 4, 0xFFE2FC40 , 0x7E2044E , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "sqrtf.s" , N850_SQRTFS , 4, 0xFFE0FC40 , 0x7E0044E , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "subf.s" , N850_SUBFS , 4, 0xFFFFFC62 , 0x7E00462 , 3, OP_TYPE_SUB, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "trncf.sl" , N850_TRNCFSL , 4, 0xFFE1F444 , 0x7E10444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "trncf.sul" , N850_TRNCFSUL , 4, 0xFFF1F444 , 0x7F10444 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f000, 12, 0, 0, 4, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "trncf.suw" , N850_TRNCFSUW , 4, 0xFFF1FC40 , 0x7F10440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "trncf.sw" , N850_TRNCFSW , 4, 0xFFE1FC40 , 0x7E00440 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "addi" , N850_ADDI , 4, 0xFE1FFFFF , 0x06000000 , 3, OP_TYPE_MOV, COND_NV, {{0x0000ffff, 0, 0, 0, 16, SIGNED, 0, TYPE_IMM}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "adf" , N850_ADF , 4, 0xFFFFFBBE , 0x7E003A0 , 4, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000001E, 1, 0, 0, 4, UNSIGNED, 0, TYPE_CCCC}, {0}}}, + { "andi" , N850_ANDI , 4, 0xFEDFFFFF , 0x06C00000 , 3, OP_TYPE_MOV, COND_NV, {{0x0000ffff, 0, 0, 0, 16, SIGNED, 0, TYPE_IMM}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "bsh" , N850_BSH , 4, 0xFFE0FB42 , 0x07e00342 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "caxi" , N850_CAXI , 4, 0xFFFFF8EE , 0x07E000EE , 3, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG_MEM}, {0}, {0}}}, + /*UNTESTED*/{ "cll" , N850_CLL , 4, 0xFFFFF160 , 0xFFFFF160 , 0, OP_TYPE_NOP, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "bins" , N850_BINS , 4, 0xFFFFF89E , 0x07e00090 , 4, OP_TYPE_MOV, COND_NV, {{0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0x0000F000, 12, 0, 0, 4, UNSIGNED, 2, TYPE_BINS}, {0x00000800, 8, 0, 0, 1, UNSIGNED, 1, TYPE_IMM}, {0x0000000E, 1, 0, 0x10, 3, UNSIGNED, 1, TYPE_IMM}}}, + { "bins" , N850_BINS2 , 4, 0xFFFFF8BE , 0x07e000B0 , 4, OP_TYPE_MOV, COND_NV, {{0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0x0000F000, 12, 0, 0, 4, UNSIGNED, 2, TYPE_BINS2}, {0x00000800, 8, 0, 0, 1, UNSIGNED, 1, TYPE_IMM}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 1, TYPE_IMM}}}, + { "bins" , N850_BINS3 , 4, 0xFFFFF8DE , 0x07e000D0 , 4, OP_TYPE_MOV, COND_NV, {{0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0x0000F000, 12, 0, 0, 4, UNSIGNED, 2, TYPE_BINS3}, {0x00000800, 8, 0, 0, 1, UNSIGNED, 1, TYPE_IMM}, {0x0000000E, 1, 0, 0, 3, UNSIGNED, 1, TYPE_IMM}}}, + { "bsw" , N850_BSW , 4, 0xFFE0FB40 , 0x07e00340 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "clr1" , N850_CLR1 , 4, 0xBFDFFFFF , 0x87c00000 , 3, OP_TYPE_MOV, COND_NV, {{0x38000000, 27, 0, 0, 3, UNSIGNED, 0, TYPE_IMM}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 1, TYPE_MEM}, {0}, {0}}}, + /*UNTESTED*/{ "clr1" , N850_CLR1R , 4, 0xFFFF00E4 , 0x07e000e4 , 2, OP_TYPE_MOV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "cmov" , N850_CMOV , 4, 0xFFFFFB3E , 0x07e00320 , 4, OP_TYPE_MOV, COND_NV, {{0x0000001E, 1, 0, 0, 4, UNSIGNED, 0, TYPE_CCCC}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0}}}, + { "cmov" , N850_CMOVI , 4, 0xFFFFFB1E , 0x07e00300 , 4, OP_TYPE_MOV, COND_NV, {{0x0000001E, 1, 0, 0, 4, UNSIGNED, 0, TYPE_CCCC}, {0x001f0000, 16, 0, 0, 5, SIGNED, 1, TYPE_IMM}, {0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0}}}, + /*UNTESTED*/{ "ctret" , N850_CTRET , 4, 0x7e00144 , 0x7e00144 , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "dbret" , N850_DBRET , 4, 0x7e00146 , 0x7e00146 , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "di" , N850_DI , 4, 0x7e00160 , 0x7e00160 , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "nop" , N850_NOP , 4, 0xFFFFF960 , 0xE7E00160 , 0, OP_TYPE_NOP, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "dispose" , N850_DISPOSE , 4, 0x67fffe0 , 0x6400000 , 2, OP_TYPE_MOV, COND_NV, {{0x003e0000, 17, 2, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0x0001ffe0, 4, 0, 0, 12, UNSIGNED, 1, TYPE_LIST}, {0x0010000, 16, 0, 0, 1, UNSIGNED, 1, TYPE_LIST}, {0}, {0}}}, + /*UNTESTED*/{ "dispose" , N850_DISPOSER , 4, 0x67fffff , 0x6400000 , 3, OP_TYPE_MOV, COND_NV, {{0x003e0000, 17, 2, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0x0001ffe0, 4, 0, 0, 12, UNSIGNED, 1, TYPE_LIST}, {0x0010000, 16, 0, 0, 1, UNSIGNED, 1, TYPE_LIST}, {0x0000001f, 0, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}}}, + { "div" , N850_DIV , 4, 0xfffffac0 , 0x7e002c0 , 3, OP_TYPE_DIV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "divh" , N850_DIVHR , 4, 0xfffffa80 , 0x7e00280 , 3, OP_TYPE_DIV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "divhu" , N850_DIVHU , 4, 0xfffffa82 , 0x7e00282 , 3, OP_TYPE_DIV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "divq" , N850_DIVQ , 4, 0xfffffafc , 0x7e002fc , 3, OP_TYPE_DIV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "divqu" , N850_DIVQU , 4, 0xfffffafe , 0x7e002fe , 3, OP_TYPE_DIV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "divu" , N850_DIVU , 4, 0xfffffac2 , 0x7e002c2 , 3, OP_TYPE_DIV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "ei" , N850_EI , 4, 0x87e00160 , 0x87e00160 , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "eiret" , N850_EIRET , 4, 0x7E00148 , 0x7E00148 , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "feret" , N850_FERET , 4, 0x7E0014A , 0x7E0014A , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "halt" , N850_HALT , 4, 0x7e00120 , 0x7e00120 , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "hsw" , N850_HSW , 4, 0xfffe0fb44 , 0x7e00344 , 2, OP_TYPE_MOV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "hsh" , N850_HSH , 4, 0xFFE0FB46 , 0x7E00346 , 2, OP_TYPE_MOV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "jr" , N850_JR , 4, 0x07bffffe , 0x07800000 , 1, OP_TYPE_JMP, COND_NV, {{0x003fffff, 0, 0, 0, 22, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0},{0}}}, + { "jarl" , N850_JARL , 4, 0xffbffffe , 0x7800000 , 2, OP_TYPE_CALL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x003fffff, 0, 0, 0, 22, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "jarl" , N850_JARL3 , 4, 0xC7FFF960 , 0xC7E00160 , 2, OP_TYPE_CALL, COND_NV, {{0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG_MEM}, {0x0000f800, 11, 0, 0, 5, SIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "ld.b" , N850_LDB , 4, 0xff1fffff , 0x7000000 , 3, OP_TYPE_LOAD, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 0, TYPE_MEM}, {0}, {0}}}, + { "ld.bu" , N850_LDBU , 4, 0xffbfffff , 0x7800000 , 3, OP_TYPE_LOAD, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x0000FFFE, 0, 0, 0, 16, SIGNED, 0, TYPE_MEM}, {0x00200000, 21, 0, 0, 1, UNSIGNED, 0, TYPE_MEM}, {0}}}, + { "ld.h" , N850_LDH , 4, 0xff3ffffe , 0x7200000 , 3, OP_TYPE_LOAD, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x0000FFFE, 0, 0, 0, 16, SIGNED, 0, TYPE_MEM}, {0}, {0}}}, + { "ld.hu" , N850_LDHU , 4, 0xffffffff , 0x7E00001 , 3, OP_TYPE_LOAD, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x0000FFFE, 0, 0, 0, 16, SIGNED, 0, TYPE_MEM}, {0}, {0}}}, + { "ld.w" , N850_LDW , 4, 0xff3fffff , 0x7200001 , 3, OP_TYPE_LOAD, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0x0000FFFE, 0, 0, 0, 16, SIGNED, 0, TYPE_MEM}, {0}, {0}}}, + { "ldsr" , N850_LDSR , 4, 0xfffff820 , 0x7E00020 , 2, OP_TYPE_LOAD, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_SYSREG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_IMM}, {0}, {0}}}, + { "movea" , N850_MOVEA , 4, 0xfe3fffff , 0x6200000 , 3, OP_TYPE_MOV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 0, TYPE_IMM}, {0}, {0}}}, + { "movhi" , N850_MOVHI , 4, 0xfe5fffff , 0x6400000 , 3, OP_TYPE_MOV, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000FFFF, 0, 0, 0, 16, UNSIGNED, 0, TYPE_IMM}, {0}, {0}}}, + { "mul" , N850_MUL , 4, 0xfffffa20 , 0x7e00220 , 3, OP_TYPE_MUL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "mul" , N850_MULI , 4, 0xfffffa7c , 0x7e00240 , 3, OP_TYPE_MUL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, SIGNED, 0, TYPE_IMM}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x0000003c, 0, 3, 0, 4, SIGNED, 0, TYPE_IMM}, {0}}}, + { "mulu" , N850_MULU , 4, 0xfffffa22 , 0x7e00222 , 3, OP_TYPE_MUL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "mulu" , N850_MULUI , 4, 0xfffffa7e , 0x7e00242 , 3, OP_TYPE_MUL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0x0000F800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x0000003c, 0, 3, 0, 4, UNSIGNED, 0, TYPE_IMM}, {0}}}, + { "not1" , N850_NOT1 , 4, 0x7fdfffff , 0x47c00000 , 3, OP_TYPE_NOT, COND_NV, {{0x38000000, 27, 0, 0, 3, UNSIGNED, 0, TYPE_IMM}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 1, TYPE_MEM}, {0}, {0}}}, + { "not1" , N850_NOT1R , 4, 0xffff00e2 , 0x07e000e2 , 2, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "ori" , N850_ORI , 4, 0xfe9fffff , 0x6800000 , 3, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000FFFF, 0, 0, 0, 16, UNSIGNED, 0, TYPE_IMM}, {0}, {0}}}, + /*UNTESTED*/{ "reti" , N850_RETI , 4, 0x7e00140 , 0x7e00140 , 0, OP_TYPE_RET, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "sar" , N850_SAR , 4, 0xffff00a0 , 0x07e000a0 , 2, OP_TYPE_SHR, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + + { "sar" , N850_SARR , 4, 0xfffff8a2 , 0x07e000a2 , 3, OP_TYPE_SHR, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + + /*UNTESTED*/{ "sasf" , N850_SASF , 4, 0xffef0200 , 0x07e00200 , 2, OP_TYPE_SHL, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x000f0000, 16, 0, 0, 4, UNSIGNED, 0, TYPE_CCCC}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "satsubi" , N850_SATSUBI , 4, 0xfe7fffff , 0x6600000 , 3, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 0, TYPE_IMM}, {0}, {0}}}, + { "set1" , N850_SET1 , 4, 0x3fdfffff , 0x7c00000 , 3, OP_TYPE_AND, COND_NV, {{0x38000000, 27, 0, 0, 3, UNSIGNED, 0, TYPE_IMM}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 1, TYPE_MEM}, {0}, {0}}}, + /*UNTESTED*/{ "set1" , N850_SET1R , 4, 0xffff00e0 , 0x07e000e0 , 2, OP_TYPE_AND, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "setf" , N850_SETF , 4, 0xffef0000 , 0x07e00000 , 2, OP_TYPE_MOV, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x000f0000, 16, 0, 0, 4, UNSIGNED, 0, TYPE_CCCC}, {0}, {0}, {0}}}, + { "shl" , N850_SHL , 4, 0xffff00c0 , 0x07e000c0 , 2, OP_TYPE_SHL, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "shr" , N850_SHR , 4, 0xffff0080 , 0x07e00080 , 2, OP_TYPE_SHR, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "shr" , N850_SHRR , 4, 0xfffff882 , 0x07e00082 , 3, OP_TYPE_SHR, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x00f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "st.b" , N850_STB , 4, 0xff5fffff , 0x7400000 , 3, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 1, TYPE_MEM}, {0}, {0}}}, + { "st.h" , N850_STH , 4, 0xff7ffffe , 0x7600000 , 3, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x0000FFFE, 0, 0, 0, 15, SIGNED, 1, TYPE_MEM}, {0}, {0}}}, + { "st.w" , N850_STW , 4, 0xff7fffff , 0x7600001 , 3, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x0000FFFE, 0, 0, 0, 15, SIGNED, 1, TYPE_MEM}, {0}, {0}}}, + { "stsr" , N850_STSR , 4, 0xffff0040 , 0x07e00040 , 2, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_SYSREG}, {0}, {0}, {0}}}, + { "stsr" , N850_STSR , 4, 0xfffff840 , 0x07e00040 , 2, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_SYSREG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_IMM}, {0}, {0}}}, + /*UNTESTED*/{ "syscall" , N850_SYSCALL , 4, 0xd7ff3960 , 0xd7e00160 , 1, OP_TYPE_CALL, COND_NV, {{0x00003800, 6, 0, 0, 3, UNSIGNED, 0, TYPE_IMM}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "trap" , N850_TRAP , 4, 0x7ff0100 , 0x7e00100 , 1, OP_TYPE_TRAP, COND_NV, {{0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0},{0}, {0}, {0}}}, + { "tst1" , N850_TST1 , 4, 0xffdfffff , 0xc7c00000 , 3, OP_TYPE_NOT, COND_NV, {{0x38000000, 27, 0, 0, 3, UNSIGNED, 0, TYPE_IMM}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 2, TYPE_REG_MEM}, {0x0000FFFF, 0, 0, 0, 16, SIGNED, 1, TYPE_MEM}, {0}, {0}}}, + /*UNTESTED*/{ "tst1" , N850_TST1R , 4, 0xffff00e6 , 0x07e000e6 , 2, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "xori" , N850_XORI , 4, 0xfeBfffff , 0x6A00000 , 3, OP_TYPE_OR, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000FFFF, 0, 0, 0, 16, UNSIGNED, 0, TYPE_IMM}, {0}, {0}}}, + /*UNTESTED*/{ "ldl.w" , N850_LDLW , 4, 0x7FFFB78 , 0x7E00378 , 2, OP_TYPE_NOT, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "mac" , N850_MAC , 4, 0xfffff3de , 0x7e003c0 , 4, OP_TYPE_MUL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000001E, 1, 1, 0, 4, UNSIGNED, 3, TYPE_REG}, {0x00f000, 12, 1, 0, 4, UNSIGNED, 2, TYPE_REG}, {0}}}, + { "macu" , N850_MACU , 4, 0xfffff3fe , 0x7e003e0 , 4, OP_TYPE_MUL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000001E, 1, 1, 0, 4, UNSIGNED, 3, TYPE_REG}, {0x00f000, 12, 1, 0, 4, UNSIGNED, 2, TYPE_REG}, {0}}}, + { "popsp" , N850_POPSP , 4, 0x67FFF960 , 0x67E00160 , 2, OP_TYPE_MUL, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "pushsp" , N850_PUSHSP , 4, 0x47FFF960 , 0x47E00160 , 2, OP_TYPE_MUL, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "rie" , N850_RIEI , 4, 0xffff0000 , 0x07f00000 , 2, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_IMM}, {0x000f0000, 16, 0, 0, 4, UNSIGNED, 0, TYPE_IMM}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "rotl" , N850_ROTL , 4, 0xfffff8c6 , 0x07e000c6 , 3, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "rotl" , N850_ROTLI , 4, 0xfffff8c4 , 0x07e000c4 , 3, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "satadd" , N850_SATADDR , 4, 0xfffffBBA , 0x07e003ba , 3, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "satsub" , N850_SATSUBL , 4, 0xfffffB9A , 0x07e0039a , 3, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "sbf" , N850_SBF , 4, 0xffffFB9E , 0x07e00380 , 4, OP_TYPE_NOT, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 3, TYPE_REG}, {0x0000001e, 1, 0, 0, 4, UNSIGNED, 0, TYPE_CCCC}, {0}}}, + /*UNTESTED*/{ "sch0l" , N850_SCH0L , 4, 0xFFE0FB64 , 0x7E00364 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "sch0r" , N850_SCH0R , 4, 0xFFE0FB60 , 0x7E00360 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "sch1l" , N850_SCH1L , 4, 0xFFE0FB66 , 0x7E00366 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "sch1r" , N850_SCH1R , 4, 0xFFE0FB62 , 0x7E00362 , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0xf8000000, 27, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}}}, + { "shl" , N850_SHLL , 4, 0xfffff8c2 , 0x07e000c2 , 3, OP_TYPE_SHL, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "shr" , N850_SHRL , 4, 0xffff0082 , 0x07e00082 , 3, OP_TYPE_SHR, COND_NV, {{0xf8000000, 27, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x0000f800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + /*UNTESTED*/{ "snooze" , N850_SNOOZE , 4, 0xfe00120 , 0xfe00120 , 0, OP_TYPE_NOP, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "stc.w" , N850_STCW , 4, 0x7fffb7a , 0x7E0037A , 2, OP_TYPE_MOV, COND_NV, {{0x0000f800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 0, TYPE_REG_MEM}, {0}, {0}, {0}}}, + { "jmp" , N850_JMPI , 6, 0x6ffffffeffff , 0x6E000000000 , 2, OP_TYPE_RJMP, COND_NV, {{0x001f00000000, 32, 0, 0, 5, UNSIGNED, 1, TYPE_REG_MEM}, {0xffff0000, 16, 0, 0, 16, UNSIGNED, 0, TYPE_MEM}, {0xffff, 0, 16, 0, 16, UNSIGNED, 0, TYPE_MEM}, {0}, {0}}}, + { "mulhi" , N850_MULHI , 4, 0xfeffffff , 0x6e00000 , 3, OP_TYPE_MUL, COND_NV, {{0xF8000000, 27, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0x001f0000, 16, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0x0000FFFF, 0, 0, 0, 16, UNSIGNED, 0, TYPE_IMM}, {0}, {0}}}, + // 2-byte Instructions +// { "name" , enum , size, mask , static_mask , n, op_type , cond , {{field ,shr,shl, +, size (in bits), sign, index, TYPE_REG}, ...} + //{ "mov" , N850_MOV , 2, 0x0000 , 2, OP_TYPE_MOV, COND_NV, {{0xf800, 10, 0, 0, TYPE_REG}, {0x001f, 0, 0, 0, TYPE_REG}, {0}, {0}}}, + { "nop" , N850_NOP , 2, 0x0000 , 0x0000 , 0, OP_TYPE_NOP, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "switch" , N850_SWITCH , 2, 0x005f , 0x0040 , 1, OP_TYPE_RJMP, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}, {0}}}, + { "sxb" , N850_SXB , 2, 0x00bf , 0x00A0 , 1, OP_TYPE_MOV, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}, {0}}}, + { "sxh" , N850_SXH , 2, 0x00ff , 0x00E0 , 1, OP_TYPE_MOV, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}, {0}}}, + { "synce" , N850_SYNCE , 2, 0x001D , 0x001D , 0, OP_TYPE_MOV, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "synci" , N850_SYNCI , 2, 0x001C , 0x001C , 0, OP_TYPE_MOV, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "syncm" , N850_SYNCM , 2, 0x001E , 0x001E , 0, OP_TYPE_MOV, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "syncp" , N850_SYNCP , 2, 0x001F , 0x001F , 0, OP_TYPE_MOV, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + { "zxb" , N850_ZXB , 2, 0x009f , 0x0080 , 1, OP_TYPE_MOV, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}, {0}}}, + { "zxh" , N850_ZXH , 2, 0x00df , 0x00C0 , 1, OP_TYPE_MOV, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}, {0}}}, + { "add" , N850_ADD , 2, 0xF9DF , 0x01c0 , 2, OP_TYPE_ADD, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "add" , N850_ADD_IMM , 2, 0xFA5F , 0x0240 , 2, OP_TYPE_ADD, COND_NV, {{0x001f, 0, 0, 0, 5, SIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "and" , N850_AND , 2, 0xF95F , 0x0140 , 2, OP_TYPE_AND, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "bge" , N850_BGE , 2, 0xFDFE , 0x058E , 1, OP_TYPE_CJMP, COND_GE, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bgt" , N850_BGT , 2, 0xFDFF , 0x058F , 1, OP_TYPE_CJMP, COND_GT, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "ble" , N850_BLE , 2, 0xFDF7 , 0x0587 , 1, OP_TYPE_CJMP, COND_LE, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "blt" , N850_BLT , 2, 0xFDF6 , 0x0586 , 1, OP_TYPE_CJMP, COND_LT, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bh" , N850_BH , 2, 0xFDFB , 0x058B , 1, OP_TYPE_CJMP, COND_H, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bl" , N850_BL , 2, 0xFDF1 , 0x0581 , 1, OP_TYPE_CJMP, COND_L, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bnh" , N850_BNH , 2, 0xFDF3 , 0x0583 , 1, OP_TYPE_CJMP, COND_NH, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "bnl" , N850_BNL , 2, 0xFDF9 , 0x0589 , 1, OP_TYPE_CJMP, COND_NL, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "be" , N850_BE , 2, 0xFDF2 , 0x0582 , 1, OP_TYPE_CJMP, COND_EQ, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bne" , N850_BNE , 2, 0xFDFA , 0x058A , 1, OP_TYPE_CJMP, COND_NE, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bc" , N850_BC , 2, 0xFDF1 , 0x0581 , 1, OP_TYPE_CJMP, COND_CA, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bn" , N850_BN , 2, 0xFDF4 , 0x0584 , 1, OP_TYPE_CJMP, COND_NEG, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bnc" , N850_BNC , 2, 0xFDF9 , 0x0589 , 1, OP_TYPE_CJMP, COND_NCA, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bnv" , N850_BNV , 2, 0xFDF8 , 0x0588 , 1, OP_TYPE_CJMP, COND_NOF, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bnz" , N850_BNZ , 2, 0xFDFA , 0x058A , 1, OP_TYPE_CJMP, COND_NZ, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bp" , N850_BP , 2, 0xFDFC , 0x058C , 1, OP_TYPE_CJMP, COND_POS, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "br" , N850_BR , 2, 0xFDF5 , 0x0585 , 1, OP_TYPE_JMP, COND_NV, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bsa" , N850_BSA , 2, 0xFDFD , 0x058D , 1, OP_TYPE_CJMP, COND_SAT, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bv" , N850_BV , 2, 0xFDF0 , 0x0580 , 1, OP_TYPE_CJMP, COND_OF, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + { "bz" , N850_BZ , 2, 0xFDF2 , 0x0582 , 1, OP_TYPE_CJMP, COND_ZERO, {{0x0070, 3, 0, 0, 4, SIGNED, 0, TYPE_JMP}, {0xf800, 7, 0, 0, 5, SIGNED, 0, TYPE_JMP}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "callt" , N850_CALLT , 2, 0x23f , 0x0200 , 1, OP_TYPE_MOV, COND_NV, {{0x003f, 0, 1, 0, 6, UNSIGNED, 0, TYPE_IMM}, {0}, {0}, {0}, {0}}}, + { "cmp" , N850_CMP , 2, 0xF9FF , 0x01E0 , 2, OP_TYPE_CMP, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "cmp" , N850_CMPI , 2, 0xFA7F , 0x0260 , 2, OP_TYPE_CMP, COND_NV, {{0x001f, 0, 0, 0, 5, SIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "dbtrap" , N850_DBTRAP , 2, 0xF840 , 0xF840 , 0, OP_TYPE_CMP, COND_NV, {{0}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "divh" , N850_DIVH, 2, 0xF85F , 0x0040 , 2, OP_TYPE_DIV, COND_NV, {{0x001f, 0, 0, 0, 5, SIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "jmp" , N850_JMP , 2, 0x007f , 0x0060 , 1, OP_TYPE_RJMP, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG_MEM}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "fetrap" , N850_FETRAP , 2, 0x7840 , 0x0040 , 1, OP_TYPE_RJMP, COND_NV, {{0x7800, 11, 0, 0, 4, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}, {0}}}, + { "mov" , N850_MOV , 2, 0xf81f , 0x0000 , 2, OP_TYPE_MOV, COND_NV, {{0x001f, 0, 0, 0, 5, SIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "mov" , N850_MOVI5 , 2, 0xfa1f , 0x0200 , 2, OP_TYPE_MOV, COND_NV, {{0x001f, 0, 0, 0, 5, SIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "mulh" , N850_MULH , 2, 0xf8ff , 0x00e0 , 2, OP_TYPE_MUL, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "mulh" , N850_MULHIMM , 2, 0xfaff , 0x02e0 , 2, OP_TYPE_MUL, COND_NV, {{0x001f, 0, 0, 0, 5, SIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "not" , N850_NOT , 2, 0xf83f , 0x0020 , 2, OP_TYPE_NOT, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "or" , N850_OR , 2, 0xf91f , 0x0100 , 2, OP_TYPE_OR, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "sar" , N850_SARI , 2, 0xfabf , 0x02A0 , 2, OP_TYPE_SHR, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "satadd" , N850_SATADD , 2, 0xf8df , 0x00c0 , 2, OP_TYPE_ADD, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "satadd" , N850_SATADDI , 2, 0xfa3f , 0x0220 , 2, OP_TYPE_ADD, COND_NV, {{0x001f, 0, 0, 0, 5, SIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "satsub" , N850_SATSUB , 2, 0xf8bf , 0x00A0 , 2, OP_TYPE_SUB, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "satsubr" , N850_SATSUBR , 2, 0xf89f , 0x0080 , 2, OP_TYPE_SUB, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "shl" , N850_SHLI , 2, 0xfadf , 0x02c0 , 2, OP_TYPE_SHL, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "shr" , N850_SHRI , 2, 0xfa9f , 0x0280 , 2, OP_TYPE_SHR, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_IMM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "sld.b" , N850_SLDB , 2, 0xfb7f , 0x0300 , 3, OP_TYPE_LOAD, COND_NV, {{0x007f, 0, 0, 0, 7, UNSIGNED, 0, TYPE_MEM}, {0x1000, 0, 0, 0, 0, UNSIGNED, 1, TYPE_EP}, {0xf800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "sld.bu" , N850_SLDBU , 2, 0xf86f , 0x0060 , 3, OP_TYPE_LOAD, COND_NV, {{0x000f, 0, 0, 0, 4, UNSIGNED, 0, TYPE_MEM}, {0x1000, 0, 0, 0, 0, UNSIGNED, 1, TYPE_EP},{0xf800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "sld.h" , N850_SLDH , 2, 0xfc7f , 0x0400 , 3, OP_TYPE_LOAD, COND_NV, {{0x007f, 0, 1, 0, 7, UNSIGNED, 0, TYPE_MEM}, {0x1000, 0, 0, 0, 0, UNSIGNED, 1, TYPE_EP},{0xf800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "sld.hu" , N850_SLDHU , 2, 0xf87f , 0x0070 , 3, OP_TYPE_LOAD, COND_NV, {{0x000f, 0, 1, 0, 4, UNSIGNED, 0, TYPE_MEM}, {0x1000, 0, 0, 0, 0, UNSIGNED, 1, TYPE_EP},{0xf800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "sld.w" , N850_SLDW , 2, 0xfd7e , 0x0500 , 3, OP_TYPE_LOAD, COND_NV, {{0x007e, 0, 1, 0, 6, UNSIGNED, 0, TYPE_MEM}, {0x1000, 0, 0, 0, 0, UNSIGNED, 1, TYPE_EP},{0xf800, 11, 0, 0, 5, UNSIGNED, 2, TYPE_REG}, {0}, {0}}}, + { "sst.b" , N850_SSTB , 2, 0xfbff , 0x0380 , 3, OP_TYPE_STORE, COND_NV, {{0x007f, 0, 0, 0, 7, UNSIGNED, 1, TYPE_MEM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x1000, 0, 0, 0, 0, UNSIGNED, 2, TYPE_EP}, {0}, {0}}}, + { "sst.h" , N850_SSTH , 2, 0xfCff , 0x0480 , 3, OP_TYPE_STORE, COND_NV, {{0x007f, 0, 1, 0, 7, UNSIGNED, 1, TYPE_MEM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x1000, 0, 0, 0, 0, UNSIGNED, 2, TYPE_EP}, {0}, {0}}}, + { "sst.w" , N850_SSTW , 2, 0xfd7f , 0x0501 , 3, OP_TYPE_STORE, COND_NV, {{0x007e, 0, 1, 0, 6, UNSIGNED, 1, TYPE_MEM}, {0xf800, 11, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0x1000, 0, 0, 0, 0, UNSIGNED, 2, TYPE_EP}, {0}, {0}}}, + { "sub" , N850_SUB , 2, 0xF9BF , 0x01a0 , 2, OP_TYPE_SUB, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "subr" , N850_SUBR , 2, 0xF99F , 0x0180 , 2, OP_TYPE_SUB, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "sxb" , N850_SXB , 2, 0x00Bf , 0x00A0 , 1, OP_TYPE_SUB, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0}, {0}, {0}, {0}}}, + /*UNTESTED*/{ "tst" , N850_TST , 2, 0xF97F , 0x0160 , 2, OP_TYPE_AND, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, + { "xor" , N850_XOR , 2, 0xf93f , 0x0120 , 2, OP_TYPE_OR, COND_NV, {{0x001f, 0, 0, 0, 5, UNSIGNED, 0, TYPE_REG}, {0xf800, 11, 0, 0, 5, UNSIGNED, 1, TYPE_REG}, {0}, {0}, {0}}}, +}; + + +insn_t *disassemble(const uint8_t *in_buffer) { + insn_t* ret_val = malloc(sizeof(insn_t)); + memset(ret_val,0,sizeof(insn_t)); + uint64_t data; + uint8_t had_partials = 0; + const disass_insn_t* current_insn; + const uint32_t insn_list_size = sizeof (instruction_list) / sizeof (disass_insn_t); + for (int insn_list_index = 0; insn_list_index < insn_list_size; insn_list_index++) { + data = 0; + current_insn = &instruction_list[insn_list_index]; + // add EP as a operand + for (int i = 0; i < current_insn->size; i+=2) { + data |= (uint64_t)in_buffer[i+1] << ((current_insn->size - (i+1)) * 8); + data |= (uint64_t)in_buffer[i] << ((current_insn->size - (i+2)) * 8); + //printf("Switching[%d] (shift: %d - shifted: 0x%lx): %x and %x: 0x%lx\n",i,((current_insn->size - i) * 8),(uint64_t)in_buffer[i+1] << ((current_insn->size - i) * 8),in_buffer[i],in_buffer[i+1],data); + } + + //printf("Converted to %x\n",(uint32_t)data); + if (((current_insn->mask & data) == data) && (current_insn->static_mask & data) == current_insn->static_mask) {// && (current_insn->mask & data) == data) { + ret_val->name = current_insn->name; + ret_val->size = current_insn->size; + ret_val->op_type = current_insn->op_type; + ret_val->cond = current_insn->cond; + ret_val->insn_id = current_insn->insn_id; + ret_val->n = current_insn->n; + for (int op_index = 0; op_index < 5; op_index++) { + if (current_insn->fields[op_index].mask == 0) continue; + uint16_t real_op_index = current_insn->fields[op_index].index; + int64_t tmp_value = data & current_insn->fields[op_index].mask; + if (current_insn->fields[op_index].type == TYPE_EP) { + ret_val->fields[real_op_index].value = 30; + ret_val->fields[real_op_index].type = TYPE_REG_MEM; + ret_val->fields[real_op_index].size += current_insn->fields[op_index].size; + ret_val->fields[real_op_index].sign = current_insn->fields[op_index].sign; + continue; + } + + tmp_value >>= current_insn->fields[op_index].shr; + tmp_value <<= current_insn->fields[op_index].shl; + tmp_value += current_insn->fields[op_index].add; + ret_val->fields[real_op_index].value |= tmp_value; + ret_val->fields[real_op_index].type = current_insn->fields[op_index].type; + ret_val->fields[real_op_index].size += current_insn->fields[op_index].size; + ret_val->fields[real_op_index].sign = current_insn->fields[op_index].sign; + // Convert to little endian + + //printf("GOT %ld\n",ret_val->fields[real_op_index].value); + } + for (int op_index = 0; op_index < 5; op_index++) + { + if ((ret_val->fields[op_index].type == TYPE_IMM || ret_val->fields[op_index].type == TYPE_JMP || ret_val->fields[op_index].type == TYPE_MEM) && ret_val->fields[op_index].sign == SIGNED) { + int64_t m = 1UL << (ret_val->fields[op_index].size - 1); + //printf("extending %d with %d",ret_val->fields[op_index].value ,m); + ret_val->fields[op_index].value = (ret_val->fields[op_index].value ^ m) - m; + } + if (ret_val->fields[op_index].type == TYPE_BINS2) { + ret_val->fields[op_index].value = ret_val->fields[op_index].value - (ret_val->fields[1].value - 1); + ret_val->fields[op_index].type = TYPE_IMM; + } else if (ret_val->fields[op_index].type == TYPE_BINS3) { + ret_val->fields[op_index].value = ret_val->fields[op_index].value - (ret_val->fields[1].value - 1); + ret_val->fields[op_index].type = TYPE_IMM; + } else if (ret_val->fields[op_index].type == TYPE_BINS) { + ret_val->fields[op_index].value = ret_val->fields[op_index].value - (ret_val->fields[1].value - 0x10) + 1; + ret_val->fields[op_index].type = TYPE_IMM; + } else if (ret_val->fields[op_index].type == TYPE_SYSREG) { + ret_val->fields[op_index].value += (ret_val->fields[2].value * 40) + 100; + } + } + return ret_val; + } + } + return NULL; +} + +/* + +typedef struct { + uint64_t value; + enum op_type type; +} insn_op_t; + +typedef struct { + const char* name; + insn_op_t fields[10]; + uint16_t n; + uint16_t size; + enum op_type op_type; + enum op_condition cond; +} insn_t; +*/ +/* +void pretty_print(insn_t* insn){ + printf("%s ",insn->name); + for (int i = 0; i < insn->n; i++) { + printf(" 0x%x,",(int64_t)insn->fields[i].value); + } + printf("\n"); +} + +int main() { + uint8_t test[] = {0x41,0x8a,0xdc,0x09}; + pretty_print(disassemble(test)); + + printf("=========================\n"); + uint8_t test2[] = {0xdc,0x09}; + pretty_print(disassemble(test2)); + printf("=========================\n"); + uint8_t test3[] = {0x06,0xf6,0x06,0x00}; + pretty_print(disassemble(test3)); + printf("=========================\n"); + uint8_t test4[] = {0x11,0x06,0x9c,0xff}; + pretty_print(disassemble(test4)); + printf("=========================\n"); + uint8_t test5[] = {0x53,0x09}; + pretty_print(disassemble(test5)); + printf("=========================\n"); + uint8_t test6[] = {0xc2,0x9e,0x63,0x00}; + pretty_print(disassemble(test6)); + printf("=========================\n"); + uint8_t test7[] = {0x9e,0x0d,0x63,0x00}; + pretty_print(disassemble(test7)); + printf("=========================\n"); + uint8_t test8[] = {0xe2,0x07,0x16,0xe3}; + pretty_print(disassemble(test8)); + return 1; +} + +*/ diff --git a/disass.h b/disass.h new file mode 100644 index 0000000..1d779f5 --- /dev/null +++ b/disass.h @@ -0,0 +1,355 @@ +#include + +#ifdef __cplusplus + extern "C" { +#endif +enum insn_id { + N850_ABSFS, + N850_ADD, + N850_ADD_IMM, + N850_ADDFS, + N850_ADF, + N850_ADDI, + N850_AND, + N850_ANDI, + N850_BGE, + N850_BGT, + N850_BLE, + N850_BLT, + N850_BH, + N850_BL, + N850_BNH, + N850_BNL, + N850_BE, + N850_BNE, + N850_BC, + N850_BN, + N850_BNC, + N850_BNV, + N850_BNZ, + N850_BP, + N850_BR, + N850_BSA, + N850_BV, + N850_BZ, + N850_BSH, + N850_BINS, + N850_BINS2, + N850_BINS3, + N850_BSW, + N850_CALLT, + N850_CAXI, + N850_CEILFSL, + N850_CEILFSUL, + N850_CEILFSUW, + N850_CEILFSW, + N850_CLL, + N850_CLR1, + N850_CLR1R, + N850_CMOV, + N850_CMOVFS, + N850_CMOVI, + N850_CMP, + N850_CMPFS, + N850_CMPI, + N850_CTRET, + N850_CVTFHS, + N850_CVTFLS, + N850_CVTFSL, + N850_CVTFSH, + N850_CVTFSUL, + N850_CVTFSUW, + N850_CVTFSW, + N850_CVTFULS, + N850_CVTFUWS, + N850_CVTFWS, + N850_DBRET, + N850_DBTRAP, + N850_DI, + N850_DISPOSE, + N850_DISPOSER, + N850_DIV, + N850_DIVFS, + N850_DIVH, + N850_DIVHR, + N850_DIVHU, + N850_DIVQ, + N850_DIVQU, + N850_DIVU, + N850_EI, + N850_EIRET, + N850_FERET, + N850_FETRAP, + N850_FLOORFSL, + N850_FLOORFSUL, + N850_FLOORFSUW, + N850_FLOORFSW, + N850_FMAFS, + N850_FMSFS, + N850_FNMAFS, + N850_FNMSFS, + N850_HALT, + N850_HSW, + N850_HSH, + N850_JARL, + N850_JARL2, + N850_JARL3, + N850_JMP, + N850_JMPI, + N850_JR, + N850_JRL, + N850_LDBL, + N850_LDBUL, + N850_LDDW, + N850_LDB, + N850_LDBU, + N850_LDH, + N850_LDHU, + N850_LDW, + N850_LDSR, + N850_MOV, + N850_MOVI5, + N850_MOVI, + N850_MOVEA, + N850_MOVHI, + N850_MAXFS, + N850_MINFS, + N850_MULFS, + N850_NEGFS, + N850_RECIPFS, + N850_ROUNDFSL, + N850_ROUNDFSUL, + N850_ROUNDFSUW, + N850_ROUNDFSW, + N850_RSQRTFS, + N850_SQRTFS, + N850_MUL, + N850_MULI, + N850_MULH, + N850_MULHIMM, + N850_MULHI, + N850_MULU, + N850_MULUI, + N850_NOP, + N850_NOT, + N850_NOT1, + N850_NOT1R, + N850_OR, + N850_ORI, + N850_PREPARE, + N850_RETI, + N850_SAR, + N850_SARI, + N850_SARR, + N850_SASF, + N850_SATADD, + N850_SATADDI, + N850_SATSUB, + N850_SATSUBI, + N850_SATSUBR, + N850_SET1, + N850_SET1R, + N850_SETF, + N850_SHL, + N850_SHLI, + N850_SHR, + N850_SHRI, + N850_SLDB, + N850_SLDBU, + N850_SLDH, + N850_SLDHU, + N850_SLDW, + N850_SSTB, + N850_SSTH, + N850_SSTW, + N850_STB, + N850_STH, + N850_STW, + N850_STSR, + N850_STSRI, + N850_SUB, + N850_SUBR, + N850_SWITCH, + N850_SXB, + N850_SXH, + N850_SYNCE, + N850_SYNCI, + N850_SYNCM, + N850_SYNCP, + N850_SYSCALL, + N850_TRAP, + N850_TST, + N850_TST1, + N850_TST1R, + N850_SUBFS, + N850_TRFSR, + N850_TRNCFSL, + N850_TRNCFSUL, + N850_TRNCFSUW, + N850_TRNCFSW, + N850_XOR, + N850_XORI, + N850_ZXB, + N850_ZXH, + N850_LDLW, + N850_LOOP, + N850_MAC, + N850_MACU, + N850_POPSP, + N850_PUSHSP, + N850_RIEI, + N850_ROTL, + N850_ROTLI, + N850_SATADDR, + N850_SATSUBL, + N850_SBF, + N850_SCH0L, + N850_SCH0R, + N850_SCH1L, + N850_SCH1R, + N850_SHLL, + N850_SHRL, + N850_SNOOZE, + N850_STCW, + N850_LDHL, + N850_LDHUL, + N850_LDWL, + N850_STDL, + N850_STDW, + N850_STHL, + N850_STWL, + N850_RIE, + N850_SHRR + +}; + + +enum op_type { + TYPE_NONE = 0, + TYPE_REG = 1, + TYPE_IMM = 2, + TYPE_MEM = 3, + TYPE_JMP = 4, + TYPE_CR = 5, + TYPE_LIST = 6, + TYPE_SYSREG = 7, + TYPE_EP = 8, + TYPE_REG_MEM = 9, + TYPE_CCCC = 10, + TYPE_COND = 11, + TYPE_LOOP = 12, + TYPE_BINS2 = 13, + TYPE_BINS3 = 14, + TYPE_BINS = 15 +}; + +enum insn_type { + OP_TYPE_ILL, +OP_TYPE_LOOP, + OP_TYPE_ADD, + OP_TYPE_SUB, + OP_TYPE_MUL, + OP_TYPE_DIV, + OP_TYPE_SHR, + OP_TYPE_SHL, + OP_TYPE_ROR, + + OP_TYPE_AND, + OP_TYPE_OR, + OP_TYPE_XOR, + OP_TYPE_NOR, + OP_TYPE_NOT, + + OP_TYPE_IO, + OP_TYPE_LOAD, + OP_TYPE_STORE, + OP_TYPE_MOV, + + OP_TYPE_CMP, + OP_TYPE_JMP, + OP_TYPE_CJMP, + OP_TYPE_CALL, + OP_TYPE_CCALL, + OP_TYPE_RJMP, + OP_TYPE_RCALL, + OP_TYPE_RET, + + OP_TYPE_SYNC, + OP_TYPE_SWI, + OP_TYPE_TRAP, + OP_TYPE_NOP +}; + +enum op_condition { + COND_AL, + COND_GE, + COND_H, + COND_NH, + COND_LE, + COND_L, + COND_NL, + COND_NE, + COND_CA, + COND_LT, + COND_GT, + COND_EQ, + COND_NEG, + COND_NZ, + COND_NCA, + COND_NOF, + COND_POS, + COND_SAT, + COND_OF, + COND_ZERO, + COND_NV +}; +/* +enum op_cond { + COND_F, + COND_UN, + COND_EQ, + COND_UEQ, + COND_OLT, + COND_ULT, + COND_OLE, + COND_ULE, + COND_SF, + COND_NGLE, + COND_SEQ, + COND_NGL, + COND_LT, + COND_NGE, + COND_LE, + COND_NGT +}; + +*/ + + +enum sign { + UNSIGNED, + SIGNED +}; + +typedef struct { + int64_t value; + uint64_t size; + enum sign sign; + enum op_type type; +} insn_op_t; + +typedef struct { + const char* name; + enum insn_id insn_id; + insn_op_t fields[10]; + uint16_t n; + uint16_t size; + enum insn_type op_type; + enum op_condition cond; +} insn_t; + +insn_t *disassemble(const uint8_t *in_buffer); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/nec850.cpp b/nec850.cpp new file mode 100644 index 0000000..9f7f353 --- /dev/null +++ b/nec850.cpp @@ -0,0 +1,6386 @@ + +#include "nec850.h" +#include "binaryninjaapi.h" +#include +#include +#include +#include +#include "disass.h" +#include "binaryninjaapi.h" +#include "binaryninjacore.h" +#include "lowlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + +static const char *reg_name[] = { + "r0", + "r1", + "r2", + "sp", + "gp", + "tp", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "r13", + "r14", + "r15", + "r16", + "r17", + "r18", + "r19", + "r20", + "r21", + "r22", + "r23", + "r24", + "r25", + "r26", + "r27", + "r28", + "r29", + "ep", + "lp", + "pc"}; + +static const char *cccc_name[] = { + "v", + "c/l", + "z", + "nh", + "s/n", + "t", + "lt", + "le", + "nv", + "nc/nl", + "nz", + "h", + "ns/p", + "INVALID", + "ge", + "gt"}; + +static const char *cond_name[] = { + "f", + "un", + "eq", + "ueq", + "olt", + "ult", + "ole", + "ule", + "sf", + "ngle", + "seq", + "ngl", + "lt", + "nge", + "le", + "ngt"}; + +static const char *reg_list_names[] = { + "r24", + "r25", + "r26", + "r27", + "r20", + "r21", + "r22", + "r23", + "r28", + "r29", + "lp", + "ep", +}; + +static const int reg_list_regs[] = { + NEC_REG_R24, + NEC_REG_R25, + NEC_REG_R26, + NEC_REG_R27, + NEC_REG_R20, + NEC_REG_R21, + NEC_REG_R22, + NEC_REG_R23, + NEC_REG_R28, + NEC_REG_R29, + NEC_REG_LP, + NEC_REG_EP +}; + +class NEC850 : public Architecture +{ +private: + BNEndianness endian; + + /* this can maybe be moved to the API later */ + BNRegisterInfo RegisterInfo(uint32_t fullWidthReg, size_t offset, size_t size, bool zeroExtend = false) + { + BNRegisterInfo result; + result.fullWidthRegister = fullWidthReg; + result.offset = offset; + result.size = size; + result.extend = zeroExtend ? ZeroExtendToFullWidth : NoExtend; + return result; + } + +public: + /* initialization list */ + NEC850(const char *name) : Architecture(name) + { + } + + /*************************************************************************/ + + std::string GetSysregName(int sysreg_id) + { + switch (sysreg_id) + { + case NEC_SYSREG_EIPC: + return "eipc"; + case NEC_SYSREG_EIPSW: + return "eipsw"; + case NEC_SYSREG_FEPC: + return "fepc"; + case NEC_SYSREG_FEPSW: + return "fepsw"; + case NEC_SYSREG_PSW: + return "psw"; + case NEC_SYSREG_FPSR: + return "fpsr"; + case NEC_SYSREG_FPEPC: + return "fpepc"; + case NEC_SYSREG_FPST: + return "fpst"; + case NEC_SYSREG_FPCC: + return "fpcc"; + case NEC_SYSREG_FPCFG: + return "fpcfg"; + case NEC_SYSREG_FPEC: + return "fpec"; + case NEC_SYSREG_EIIC: + return "eiic"; + case NEC_SYSREG_FEIC: + return "feic"; + case NEC_SYSREG_CTPC: + return "ctpc"; + case NEC_SYSREG_CTPSW: + return "ctpsw"; + case NEC_SYSREG_CTBP: + return "ctbp"; + case NEC_SYSREG_EIWR: + return "eiwr"; + case NEC_SYSREG_FEWR: + return "fewr"; + case NEC_SYSREG_BSEL: + return "bsel"; + case NEC_SYSREG_MCFG0: + return "mcfg0"; + case NEC_SYSREG_RBASE: + return "rbase"; + case NEC_SYSREG_EBASE: + return "ebase"; + case NEC_SYSREG_INTBP: + return "intbp"; + case NEC_SYSREG_MCTL: + return "mctl"; + case NEC_SYSREG_PID: + return "pid"; + case NEC_SYSREG_SCCFG: + return "sccfg"; + case NEC_SYSREG_SCBP: + return "scbp"; + case NEC_SYSREG_HTCFG0: + return "htcfg0"; + case NEC_SYSREG_MEA: + return "mea"; + case NEC_SYSREG_ASID: + return "asid"; + case NEC_SYSREG_MEI: + return "mei"; + default: + return "INVALID"; + } + } + + virtual BNEndianness GetEndianness() const override + { + // MYLOG("%s()\n", __func__); + return LittleEndian; + } + + virtual size_t GetAddressSize() const override + { + // MYLOG("%s()\n", __func__); + return 4; + } + + virtual size_t GetDefaultIntegerSize() const override + { + return 4; + } + + virtual size_t GetInstructionAlignment() const override + { + return 2; + } + + virtual size_t GetMaxInstructionLength() const override + { + return 8; + } + + virtual vector GetAllFlags() override + { + return vector{ + FLAG_SAT, + FLAG_CY, + FLAG_OV, + FLAG_S, + FLAG_Z}; + } + + virtual string GetFlagName(uint32_t flag) override + { + switch (flag) + { + case FLAG_SAT: + return "sat"; + case FLAG_CY: + return "cy"; + case FLAG_OV: + return "ov"; + case FLAG_S: + return "s"; + case FLAG_Z: + return "z"; + default: + return "ERR_FLAG_NAME"; + } + } + + virtual vector GetAllFlagWriteTypes() override + { + return vector{ + FLAG_WRITE_NONE, + FLAG_WRITE_ALL, + FLAG_WRITE_OVSZ, + FLAG_WRITE_Z, + FLAG_WRITE_SZ, + FLAG_WRITE_CYSZ}; + } + + virtual string GetFlagWriteTypeName(uint32_t writeType) override + { + switch (writeType) + { + case FLAG_WRITE_CYSZ: + return "cysz"; + case FLAG_WRITE_SZ: + return "sz"; + case FLAG_WRITE_OVSZ: + return "ovsz"; + case FLAG_WRITE_CYOVSZ: + return "cyovsz"; + case FLAG_WRITE_Z: + return "z"; + case FLAG_WRITE_ALL: + return "*"; + default: + return "none"; + } + } + + virtual vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override + { + switch (writeType) + { + case FLAG_WRITE_CYSZ: + return vector{ + FLAG_CY, FLAG_Z, FLAG_S}; + case FLAG_WRITE_SZ: + return vector{ + FLAG_Z, FLAG_S}; + case FLAG_WRITE_OVSZ: + return vector{ + FLAG_Z, FLAG_S, FLAG_OV}; + case FLAG_WRITE_CYOVSZ: + return vector{ + FLAG_Z, FLAG_S, FLAG_OV, FLAG_CY}; + case FLAG_WRITE_ALL: + return vector{ + FLAG_CY, FLAG_Z, FLAG_OV, FLAG_S}; + case FLAG_WRITE_Z: + return vector{ + FLAG_Z}; + default: + return vector(); + } + } + + virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass) override + { + bool signedClass = true; + + switch (flag) + { + case FLAG_SAT: + return SpecialFlagRole; + case FLAG_CY: + return CarryFlagRole; + case FLAG_Z: + return ZeroFlagRole; + case FLAG_OV: + return OverflowFlagRole; + case FLAG_S: + return NegativeSignFlagRole; + default: + return SpecialFlagRole; + } + } + + virtual vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t) override + { + + switch (cond) + { + case LLFC_E: /* equal */ + case LLFC_NE: /* not equal */ + return vector{FLAG_Z}; + + case LLFC_ULT: /* (unsigned) less than == LT */ + case LLFC_UGE: /* (unsigned) greater-or-equal == !LT */ + return vector{FLAG_CY}; + + case LLFC_UGT: /* (unsigned) greater-than == GT */ + case LLFC_ULE: /* (unsigned) less-or-equal == !GT */ + return vector{FLAG_CY, FLAG_Z}; + + case LLFC_SLT: /* (signed) less than == LT */ + case LLFC_SGE: /* (signed) greater-or-equal == !LT */ + return vector{FLAG_S, FLAG_OV}; + + case LLFC_SGT: /* (signed) greater-than == GT */ + case LLFC_SLE: /* (signed) lesser-or-equal == !GT */ + return vector{FLAG_S, FLAG_OV, FLAG_Z}; + + case LLFC_NEG: + case LLFC_POS: + return vector{FLAG_S}; + + case LLFC_O: + case LLFC_NO: + return vector{ + FLAG_OV}; + + default: + return vector(); + } + } + + virtual vector GetFullWidthRegisters() override + { + + return vector{ + NEC_REG_R0, NEC_REG_R1, NEC_REG_R2, NEC_REG_SP, NEC_REG_R4, NEC_REG_R5, NEC_REG_R6, NEC_REG_R7, + NEC_REG_R8, NEC_REG_R9, NEC_REG_R10, NEC_REG_R11, NEC_REG_R12, NEC_REG_R13, NEC_REG_R14, NEC_REG_R15, + NEC_REG_R16, NEC_REG_R17, NEC_REG_R18, NEC_REG_R19, NEC_REG_R20, NEC_REG_R21, NEC_REG_R22, NEC_REG_R23, + NEC_REG_R24, NEC_REG_R25, NEC_REG_R26, NEC_REG_R27, NEC_REG_R28, NEC_REG_R29, NEC_REG_EP, NEC_REG_LP, NEC_REG_PC}; + } + + virtual vector GetAllRegisters() override + { + vector result = { + NEC_REG_R0, NEC_REG_R1, NEC_REG_R2, NEC_REG_SP, NEC_REG_R4, NEC_REG_R5, NEC_REG_R6, NEC_REG_R7, + NEC_REG_R8, NEC_REG_R9, NEC_REG_R10, NEC_REG_R11, NEC_REG_R12, NEC_REG_R13, NEC_REG_R14, NEC_REG_R15, + NEC_REG_R16, NEC_REG_R17, NEC_REG_R18, NEC_REG_R19, NEC_REG_R20, NEC_REG_R21, NEC_REG_R22, NEC_REG_R23, + NEC_REG_R24, NEC_REG_R25, NEC_REG_R26, NEC_REG_R27, NEC_REG_R28, NEC_REG_R29, NEC_REG_EP, NEC_REG_LP, NEC_REG_PC, + // system registers + NEC_SYSREG_EIPC, + NEC_SYSREG_EIPSW, + NEC_SYSREG_FEPC, + NEC_SYSREG_FEPSW, + NEC_SYSREG_PSW, + NEC_SYSREG_FPSR, + NEC_SYSREG_FPEPC, + NEC_SYSREG_FPST, + NEC_SYSREG_FPCC, + NEC_SYSREG_FPCFG, + NEC_SYSREG_FPEC, + NEC_SYSREG_EIIC, + NEC_SYSREG_FEIC, + NEC_SYSREG_CTPC, + NEC_SYSREG_CTPSW, + NEC_SYSREG_CTBP, + NEC_SYSREG_EIWR, + NEC_SYSREG_FEWR, + NEC_SYSREG_BSEL, + NEC_SYSREG_MCFG0, + NEC_SYSREG_RBASE, + NEC_SYSREG_EBASE, + NEC_SYSREG_INTBP, + NEC_SYSREG_MCTL, + NEC_SYSREG_PID, + NEC_SYSREG_SCCFG, + NEC_SYSREG_SCBP, + NEC_SYSREG_HTCFG0, + NEC_SYSREG_MEA, + NEC_SYSREG_ASID, + NEC_SYSREG_MEI}; + + return result; + } + + virtual vector GetSystemRegisters() override + { + vector result = { + NEC_SYSREG_EIPC, + NEC_SYSREG_EIPSW, + NEC_SYSREG_FEPC, + NEC_SYSREG_FEPSW, + NEC_SYSREG_PSW, + NEC_SYSREG_FPSR, + NEC_SYSREG_FPEPC, + NEC_SYSREG_FPST, + NEC_SYSREG_FPCC, + NEC_SYSREG_FPCFG, + NEC_SYSREG_FPEC, + NEC_SYSREG_EIIC, + NEC_SYSREG_FEIC, + NEC_SYSREG_CTPC, + NEC_SYSREG_CTPSW, + NEC_SYSREG_CTBP, + NEC_SYSREG_EIWR, + NEC_SYSREG_FEWR, + NEC_SYSREG_BSEL, + NEC_SYSREG_MCFG0, + NEC_SYSREG_RBASE, + NEC_SYSREG_EBASE, + NEC_SYSREG_INTBP, + NEC_SYSREG_MCTL, + NEC_SYSREG_PID, + NEC_SYSREG_SCCFG, + NEC_SYSREG_SCBP, + NEC_SYSREG_HTCFG0, + NEC_SYSREG_MEA, + NEC_SYSREG_ASID, + NEC_SYSREG_MEI + + }; + + return result; + } + + virtual std::vector GetGlobalRegisters() override + { + return vector{NEC_REG_PC}; + } + + virtual string GetRegisterName(uint32_t regId) override + { + const char *result; + + if (regId >= NEC_REG_R0 && regId <= NEC_REG_PC) + result = reg_name[regId]; + else if (regId >= NEC_SYSREG_EIPC && regId <= NEC_SYSREG_MEI) + return GetSysregName(regId); + else + result = ""; + return result; + } + + ExprId get_reg(LowLevelILFunction &il, int reg_id, int size) { + if (reg_id == 0) + return il.Const(size, 0); + else + return il.Register(size, reg_id); + } + + virtual BNRegisterInfo GetRegisterInfo(uint32_t regId) override + { + switch (regId) + { + // BNRegisterInfo RegisterInfo(uint32_t fullWidthReg, size_t offset, + // size_t size, bool zeroExtend = false) + + case NEC_REG_R0: + return RegisterInfo(NEC_REG_R0, 0, 4); + case NEC_REG_R1: + return RegisterInfo(NEC_REG_R1, 0, 4); + case NEC_REG_R2: + return RegisterInfo(NEC_REG_R2, 0, 4); + case NEC_REG_SP: + return RegisterInfo(NEC_REG_SP, 0, 4); + case NEC_REG_R4: + return RegisterInfo(NEC_REG_R4, 0, 4); + case NEC_REG_R5: + return RegisterInfo(NEC_REG_R5, 0, 4); + case NEC_REG_R6: + return RegisterInfo(NEC_REG_R6, 0, 4); + case NEC_REG_R7: + return RegisterInfo(NEC_REG_R7, 0, 4); + case NEC_REG_R8: + return RegisterInfo(NEC_REG_R8, 0, 4); + case NEC_REG_R9: + return RegisterInfo(NEC_REG_R9, 0, 4); + case NEC_REG_R10: + return RegisterInfo(NEC_REG_R10, 0, 4); + case NEC_REG_R11: + return RegisterInfo(NEC_REG_R11, 0, 4); + case NEC_REG_R12: + return RegisterInfo(NEC_REG_R12, 0, 4); + case NEC_REG_R13: + return RegisterInfo(NEC_REG_R13, 0, 4); + case NEC_REG_R14: + return RegisterInfo(NEC_REG_R14, 0, 4); + case NEC_REG_R15: + return RegisterInfo(NEC_REG_R15, 0, 4); + case NEC_REG_R16: + return RegisterInfo(NEC_REG_R16, 0, 4); + case NEC_REG_R17: + return RegisterInfo(NEC_REG_R17, 0, 4); + case NEC_REG_R18: + return RegisterInfo(NEC_REG_R18, 0, 4); + case NEC_REG_R19: + return RegisterInfo(NEC_REG_R19, 0, 4); + case NEC_REG_R20: + return RegisterInfo(NEC_REG_R20, 0, 4); + case NEC_REG_R21: + return RegisterInfo(NEC_REG_R21, 0, 4); + case NEC_REG_R22: + return RegisterInfo(NEC_REG_R22, 0, 4); + case NEC_REG_R23: + return RegisterInfo(NEC_REG_R23, 0, 4); + case NEC_REG_R24: + return RegisterInfo(NEC_REG_R24, 0, 4); + case NEC_REG_R25: + return RegisterInfo(NEC_REG_R25, 0, 4); + case NEC_REG_R26: + return RegisterInfo(NEC_REG_R26, 0, 4); + case NEC_REG_R27: + return RegisterInfo(NEC_REG_R27, 0, 4); + case NEC_REG_R28: + return RegisterInfo(NEC_REG_R28, 0, 4); + case NEC_REG_EP: + return RegisterInfo(NEC_REG_EP, 0, 4); + case NEC_REG_LP: + return RegisterInfo(NEC_REG_LP, 0, 4); + case NEC_REG_PC: + return RegisterInfo(NEC_REG_PC, 0, 4); + case NEC_SYSREG_EIPC: + return RegisterInfo(NEC_SYSREG_EIPC, 0, 4); + case NEC_SYSREG_EIPSW: + return RegisterInfo(NEC_SYSREG_EIPSW, 0, 4); + case NEC_SYSREG_FEPC: + return RegisterInfo(NEC_SYSREG_FEPC, 0, 4); + case NEC_SYSREG_FEPSW: + return RegisterInfo(NEC_SYSREG_FEPSW, 0, 4); + case NEC_SYSREG_PSW: + return RegisterInfo(NEC_SYSREG_PSW, 0, 4); + case NEC_SYSREG_FPSR: + return RegisterInfo(NEC_SYSREG_FPSR, 0, 4); + case NEC_SYSREG_FPEPC: + return RegisterInfo(NEC_SYSREG_FPEPC, 0, 4); + case NEC_SYSREG_FPST: + return RegisterInfo(NEC_SYSREG_FPST, 0, 4); + case NEC_SYSREG_FPCC: + return RegisterInfo(NEC_SYSREG_FPCC, 0, 4); + case NEC_SYSREG_FPCFG: + return RegisterInfo(NEC_SYSREG_FPCFG, 0, 4); + case NEC_SYSREG_FPEC: + return RegisterInfo(NEC_SYSREG_FPEC, 0, 4); + case NEC_SYSREG_EIIC: + return RegisterInfo(NEC_SYSREG_EIIC, 0, 4); + case NEC_SYSREG_FEIC: + return RegisterInfo(NEC_SYSREG_FEIC, 0, 4); + case NEC_SYSREG_CTPC: + return RegisterInfo(NEC_SYSREG_CTPC, 0, 4); + case NEC_SYSREG_CTPSW: + return RegisterInfo(NEC_SYSREG_CTPSW, 0, 4); + case NEC_SYSREG_CTBP: + return RegisterInfo(NEC_SYSREG_CTBP, 0, 4); + case NEC_SYSREG_EIWR: + return RegisterInfo(NEC_SYSREG_EIWR, 0, 4); + case NEC_SYSREG_FEWR: + return RegisterInfo(NEC_SYSREG_FEWR, 0, 4); + case NEC_SYSREG_BSEL: + return RegisterInfo(NEC_SYSREG_BSEL, 0, 4); + case NEC_SYSREG_MCFG0: + return RegisterInfo(NEC_SYSREG_MCFG0, 0, 4); + case NEC_SYSREG_RBASE: + return RegisterInfo(NEC_SYSREG_RBASE, 0, 4); + case NEC_SYSREG_EBASE: + return RegisterInfo(NEC_SYSREG_EBASE, 0, 4); + case NEC_SYSREG_INTBP: + return RegisterInfo(NEC_SYSREG_INTBP, 0, 4); + case NEC_SYSREG_MCTL: + return RegisterInfo(NEC_SYSREG_MCTL, 0, 4); + case NEC_SYSREG_PID: + return RegisterInfo(NEC_SYSREG_PID, 0, 4); + case NEC_SYSREG_SCCFG: + return RegisterInfo(NEC_SYSREG_SCCFG, 0, 4); + case NEC_SYSREG_SCBP: + return RegisterInfo(NEC_SYSREG_SCBP, 0, 4); + case NEC_SYSREG_HTCFG0: + return RegisterInfo(NEC_SYSREG_HTCFG0, 0, 4); + case NEC_SYSREG_MEA: + return RegisterInfo(NEC_SYSREG_MEA, 0, 4); + case NEC_SYSREG_ASID: + return RegisterInfo(NEC_SYSREG_ASID, 0, 4); + case NEC_SYSREG_MEI: + return RegisterInfo(NEC_SYSREG_MEI, 0, 4); + default: + // LogError("%s(%d == \"%s\") invalid argument", __func__, + // regId, powerpc_reg_to_str(regId)); + return RegisterInfo(0, 0, 0); + } + } + + virtual uint32_t GetStackPointerRegister() override + { + return NEC_REG_SP; + } + + virtual uint32_t GetLinkRegister() override + { + return NEC_REG_LP; + } + + +virtual std::string GetIntrinsicName (uint32_t intrinsic) override { + switch (intrinsic) { + case SCH1L_INTRINSIC: + return "_CountLeadingZeros"; + case SCH1R_INTRINSIC: + return "_CountTrailingZeros"; + case SCH0L_INTRINSIC: + return "_CountLeadingOnes"; + case SCH0R_INTRINSIC: + return "_CountTrailingOnes"; + case SYNC_MEMORY_ACCESS: + return "_SynchornizeMemoryAccess"; + case SYNC_PIPELINE: + return "_SynchornizePipeline"; + case SYNC_INSN_FETCHER: + return "_SynchornizeInstructionFetcher"; + case SYNC_EXCEPTIONS: + return "_SynchornizeExceptions"; + case CLL_INTRINSIC: + return "_ClearAtomicManipulationLink"; + case SNOOZE_INTRINSIC: + return "_ClearAtomicManipulationLink"; + case DI_INTRINSIC: + return "_DisableEILevelMaskableInterrupt"; + case EI_INTRINSIC: + return "_EnableEILevelMaskableException"; + case HALT_INTRINSIC: + return "_HaltCPU"; + case RIE_INTRINSIC: + return "_ReservedInstructionException"; + default: + return ""; + } + } + + virtual std::vector GetAllIntrinsics() override { + return vector { + SCH1L_INTRINSIC, + SCH1R_INTRINSIC, + SCH0L_INTRINSIC, + SCH0R_INTRINSIC, + SYNC_MEMORY_ACCESS, + SYNC_PIPELINE, + SYNC_INSN_FETCHER, + SYNC_EXCEPTIONS, + CLL_INTRINSIC, + SNOOZE_INTRINSIC, + DI_INTRINSIC, + EI_INTRINSIC, + HALT_INTRINSIC, + RIE_INTRINSIC + }; + } + + virtual std::vector GetIntrinsicInputs (uint32_t intrinsic) override { + switch (intrinsic) + { + case SCH1L_INTRINSIC: + return { + NameAndType("WORD", Type::IntegerType(4, false)) + }; + case SCH1R_INTRINSIC: + return { + NameAndType("WORD", Type::IntegerType(4, false)) + }; + case SCH0L_INTRINSIC: + return { + NameAndType("WORD", Type::IntegerType(4, false)) + }; + case SCH0R_INTRINSIC: + return { + NameAndType("WORD", Type::IntegerType(4, false)) + }; + case SYNC_MEMORY_ACCESS: + return { }; + case SYNC_PIPELINE: + return { }; + case SYNC_INSN_FETCHER: + return { }; + case SYNC_EXCEPTIONS: + return { }; + case CLL_INTRINSIC: + return { }; + case SNOOZE_INTRINSIC: + return { }; + case DI_INTRINSIC: + return { }; + case EI_INTRINSIC: + return { }; + case HALT_INTRINSIC: + return { }; + case RIE_INTRINSIC: + return { }; + default: + return vector(); + } + } + + virtual std::vector>> GetIntrinsicOutputs (uint32_t intrinsic) override { + switch (intrinsic) + { + case SCH1L_INTRINSIC: + return { Type::IntegerType(4, false) }; + case SCH1R_INTRINSIC: + return { Type::IntegerType(4, false) }; + case SCH0L_INTRINSIC: + return { Type::IntegerType(4, false) }; + case SCH0R_INTRINSIC: + return { Type::IntegerType(4, false) }; + case SYNC_MEMORY_ACCESS: + return { }; + case SYNC_PIPELINE: + return { }; + case SYNC_INSN_FETCHER: + return { }; + case SYNC_EXCEPTIONS: + return { }; + case CLL_INTRINSIC: + return { }; + case SNOOZE_INTRINSIC: + return { }; + case DI_INTRINSIC: + return { }; + case EI_INTRINSIC: + return { }; + case HALT_INTRINSIC: + return { }; + case RIE_INTRINSIC: + return { }; + default: + return vector>>(); + } + } + + virtual bool GetInstructionLowLevelIL(const uint8_t *data, uint64_t addr, size_t &len, LowLevelILFunction &il) override + { + insn_t *insn; + if ((insn = disassemble(data))) + { + len = insn->size; + BNLowLevelILLabel *true_label = NULL; + BNLowLevelILLabel *false_label = NULL; + LowLevelILLabel true_tag; + LowLevelILLabel false_tag; + LowLevelILLabel end_tag; + ExprId condition; + switch (insn->insn_id) + { + case N850_ABSFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatAbs( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_ADD: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } + break; + case N850_ADD_IMM: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } + break; + case N850_ADDFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatAdd( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_ADF: + { + if (insn->fields[0].value == 5) { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Add( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4) + ), + il.Const( + 4, + 1 + ), + FLAG_WRITE_CYOVSZ + + ) + + ) + ); + } else { + switch (insn->fields[0].value) + { + case 2: + condition = il.FlagCondition(LLFC_E); + break; + case 10: + condition = il.FlagCondition(LLFC_NE); + break; + case 11: + condition = il.FlagCondition(LLFC_UGT); + break; + case 3: + condition = il.FlagCondition(LLFC_ULE); + break; + case 0: + condition = il.FlagCondition(LLFC_O); + break; + case 8: + condition = il.FlagCondition(LLFC_NO); + break; + case 1: + condition = il.FlagCondition(LLFC_ULT); + break; + case 9: + condition = il.FlagCondition(LLFC_UGE); + break; + case 6: + condition = il.FlagCondition(LLFC_SLT); + break; + case 14: + condition = il.FlagCondition(LLFC_SGE); + break; + case 7: + condition = il.FlagCondition(LLFC_SLE); + break; + case 15: + condition = il.FlagCondition(LLFC_SGT); + break; + case 4: + condition = il.FlagCondition(LLFC_NEG); + break; + case 12: + condition = il.FlagCondition(LLFC_POS); + break; + default: + break; + } + + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Add( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4) + ), + il.Const( + 4, + 1 + ), + FLAG_WRITE_CYOVSZ + + ) + + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4), + FLAG_WRITE_CYOVSZ + ) + ) + ); + il.MarkLabel(end_tag); + + } + + } + break; + case N850_ADDI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } + break; + case N850_AND: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.And( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_ANDI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.And( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_BGE: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_SGE); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BGT: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_SGT); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BLE: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_SLE); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BLT: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_SLT); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BH: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_UGT); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BL: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_ULT); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BNH: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_ULE); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BNL: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_UGE); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BE: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_E); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BNE: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_NE); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BC: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_ULT); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BN: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_NEG); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BNC: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_UGE); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BNV: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_NO); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BNZ: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_NE); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BP: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_POS); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BR: + { + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + } + break; + case N850_BSA: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.Flag(FLAG_SAT); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BV: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_O); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BZ: + { + // True branch + true_label = il.GetLabelForAddress(this, insn->fields[0].value); + // False Branch + false_label = il.GetLabelForAddress(this, ((uint32_t) addr + insn->size)); + condition = il.FlagCondition(LLFC_E); + if (true_label && false_label) + il.AddInstruction(il.If(condition,*true_label,*false_label)); + else if (true_label) + il.AddInstruction(il.If(condition,*true_label,false_tag)); + else if (false_label) + il.AddInstruction(il.If(condition,true_tag,*false_label)); + else + il.AddInstruction(il.If(condition,true_tag,false_tag)); + + if (!true_label) { + il.MarkLabel(true_tag); + } + + il.AddInstruction(il.Jump(il.ConstPointer(4,(insn->fields[0].value + addr) & 0xFFFFFFFF))); + + if (!false_label) { + il.MarkLabel(false_tag); + } + } + break; + case N850_BSH: + { + // TODO test + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Or( + 4, + il.Or( + 4, + il.ShiftLeft( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff + ) + ), + il.Const( + 4, + 8 + ) + ), + il.LogicalShiftRight( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff00 + ) + ), + il.Const( + 4, + 8 + ) + ) + + ), + il.Or( + 4, + il.LogicalShiftRight( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff000000 + ) + ), + il.Const( + 4, + 8 + ) + ), + il.ShiftLeft( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff0000 + ) + ), + il.Const( + 4, + 8 + ) + ) + ) + ) + ) + ); + } + break; + case N850_BINS: + { + // TODO check disassembly again + // 🚫001ac798 bins r29, 0x10, 0x8, r8 + // 🚫001ac798 bins r29, 0x10, 0x7, r8 + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Or( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[3].value,4), + il.Const( + 4, + ((0xffffffff << (insn->fields[1].value + insn->fields[2].value)) & 0xffffffff | (0xffffffff >> (32 - insn->fields[1].value))) & 0xffffffff + ) + ), + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + (0xffffffff >> (32 - insn->fields[2].value) << insn->fields[1].value) & 0xffffffff + ) + ) + ) + ) + ); + } + break; + case N850_BINS2: + { + // 🚫0012ab84 bins r2, 0xf, 0x3, r1 + // 🚫0012ab84 bins r2, 0xf, 0x1, r1 - RAW + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Or( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[3].value,4), + il.Const( + 4, + //(0xffffffff << (insn->fields[1].value + insn->fields[2].value - 1)) & 0xffffffff | (0xffffffff >> (31 - insn->fields[1].value)) + ((0xffffffff << (insn->fields[1].value + insn->fields[2].value)) & 0xffffffff | (0xffffffff >> (32 - insn->fields[1].value))) & 0xffffffff + ) + ), + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + //(0xffffffff >> (32 - insn->fields[2].value)) & 0xffffffff + (0xffffffff >> (32 - insn->fields[2].value) << insn->fields[1].value) & 0xffffffff + ) + ) + ) + ) + ); + } + break; + case N850_BINS3: + { + // 🚫0012a8b8 bins r2, 0x0, 0x4, r1 + // 🚫0012a8b8 bins r2, 0x0, 0x3, r1 - RAW + /* + pos = 1 + width = 2 + msb = pos + width - 1 + lsb = pos + */ + //LogInfo("BINS AT %x",addr); // , + // 00152dd2: + //00152dd2 bins r1, 0x2, 0x7, r2 - > RAW + //00152dd2 bins r1, 0x2, 0x6, r2 + + // 008536ba: + //008536ba bins r23, 0x8, 0xf, r15 -> RAW + //008536ba bins r23, 0x8, 0x8, r15 + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Or( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[3].value,4), + il.Const( + 4, + //(0xffffffff << (insn->fields[1].value + insn->fields[2].value - 1)) & 0xffffffff | (0xffffffff >> (31 - insn->fields[1].value)) + ((0xffffffff << (insn->fields[1].value + insn->fields[2].value)) & 0xffffffff | (0xffffffff >> (32 - insn->fields[1].value))) & 0xffffffff + ) + ), + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + //(0xffffffff >> (32 - insn->fields[2].value)) & 0xffffffff + (0xffffffff >> (32 - insn->fields[2].value) << insn->fields[1].value) & 0xffffffff + ) + ) + ) + ) + ); + } + break; + case N850_BSW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Or( + 4, + il.Or( + 4, + il.ShiftLeft( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff + ) + ), + il.Const( + 4, + 24 + ) + ), + il.ShiftLeft( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff00 + ) + ), + il.Const( + 4, + 8 + ) + ) + + ), + il.Or( + 4, + il.LogicalShiftRight( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff000000 + ) + ), + il.Const( + 4, + 24 + ) + ), + il.LogicalShiftRight( + 4, + il.And( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0xff0000 + ) + ), + il.Const( + 4, + 8 + ) + ) + ) + ) + ) + ); + } + break; + case N850_CALLT: + { + il.AddInstruction( + il.Call( + il.Load( + 4, + il.Add( + 4, + il.Register( + 4, + NEC_SYSREG_CTBP + ), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ) + ) + ) + ) + ); + } + break; + case N850_CAXI: + { + // TODO not checked + il.AddInstruction( + il.If( + il.CompareEqual( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.Load( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ), + true_tag, + false_tag + ) + ); + il.MarkLabel(true_tag); + il.AddInstruction( + il.Store( + 4, + this->get_reg(il,insn->fields[0].value,4), + this->get_reg(il,insn->fields[2].value,4) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Load( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.Store( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Load( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Load( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + il.MarkLabel(end_tag); + } + break; + case N850_CEILFSL: + { + // TODO none of the CEILs are checked + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value, + il.Ceil( + 8, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CEILFSUL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value, + il.Ceil( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_CEILFSUW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Ceil( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CEILFSW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Ceil( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CLL: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + CLL_INTRINSIC, + { } // Inputs + ) + ); + } + break; + case N850_CLR1: + { + il.AddInstruction( + il.Store( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ), + il.And( + 1, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ) + ), + il.Const( + 1, + ~(1 << insn->fields[0].value) & 0xff + //((1 << (instr->fields[4].value - instr->fields[3].value + 1)) - 1) << (31 - instr->fields[4].value) + ), + FLAG_WRITE_Z + ) + + ) + ); + } + break; + case N850_CLR1R: + { + il.AddInstruction( + il.Store( + 1, + this->get_reg(il,insn->fields[1].value,4), + il.And( + 1, + il.Load( + 1, + this->get_reg(il,insn->fields[1].value,4) + ), + il.ShiftLeft( + 1, + il.Const( + 1, + 1 + ), + this->get_reg(il,insn->fields[0].value,1) + ), + FLAG_WRITE_Z + ) + ) + ); + } + break; + case N850_CMOV: + { + if (insn->fields[0].value == 5) { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + this->get_reg(il,insn->fields[1].value,4) + ) + ); + } else { + switch (insn->fields[0].value) + { + case 2: + condition = il.FlagCondition(LLFC_E); + break; + case 10: + condition = il.FlagCondition(LLFC_NE); + break; + case 11: + condition = il.FlagCondition(LLFC_UGT); + break; + case 3: + condition = il.FlagCondition(LLFC_ULE); + break; + case 0: + condition = il.FlagCondition(LLFC_O); + break; + case 8: + condition = il.FlagCondition(LLFC_NO); + break; + case 1: + condition = il.FlagCondition(LLFC_ULT); + break; + case 9: + condition = il.FlagCondition(LLFC_UGE); + break; + case 6: + condition = il.FlagCondition(LLFC_SLT); + break; + case 14: + condition = il.FlagCondition(LLFC_SGE); + break; + case 7: + condition = il.FlagCondition(LLFC_SLE); + break; + case 15: + condition = il.FlagCondition(LLFC_SGT); + break; + case 4: + condition = il.FlagCondition(LLFC_NEG); + break; + case 12: + condition = il.FlagCondition(LLFC_POS); + break; + case 13: + condition = il.CompareEqual( + 4, + il.Flag( + FLAG_SAT + ), + il.Const( + 4, + 1 + ) + ); + break; + default: + break; + } + + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + this->get_reg(il,insn->fields[1].value,4) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + this->get_reg(il,insn->fields[2].value,4) + ) + ); + il.MarkLabel(end_tag); + } + + } + break; + case N850_CMOVFS: + { + condition = il.CompareEqual( + 1, + il.Register(4,NEC_SYSREG_FPSR), + il.Const( + 1, + insn->fields[0].value + ) + + ); + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + this->get_reg(il,insn->fields[1].value,4) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + this->get_reg(il,insn->fields[2].value,4) + ) + ); + il.MarkLabel(end_tag); + } + break; + case N850_CMOVI: + { + if (insn->fields[0].value == 5) { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.SignExtend( + 4, + il.Const( + 1, + insn->fields[1].value + ) + ) + ) + ); + } else { + switch (insn->fields[0].value) + { + case 2: + condition = il.FlagCondition(LLFC_E); + break; + case 10: + condition = il.FlagCondition(LLFC_NE); + break; + case 11: + condition = il.FlagCondition(LLFC_UGT); + break; + case 3: + condition = il.FlagCondition(LLFC_ULE); + break; + case 0: + condition = il.FlagCondition(LLFC_O); + break; + case 8: + condition = il.FlagCondition(LLFC_NO); + break; + case 1: + condition = il.FlagCondition(LLFC_ULT); + break; + case 9: + condition = il.FlagCondition(LLFC_UGE); + break; + case 6: + condition = il.FlagCondition(LLFC_SLT); + break; + case 14: + condition = il.FlagCondition(LLFC_SGE); + break; + case 7: + condition = il.FlagCondition(LLFC_SLE); + break; + case 15: + condition = il.FlagCondition(LLFC_SGT); + break; + case 4: + condition = il.FlagCondition(LLFC_NEG); + break; + case 12: + condition = il.FlagCondition(LLFC_POS); + break; + case 13: + condition = il.CompareEqual( + 4, + il.Flag( + FLAG_SAT + ), + il.Const( + 4, + 1 + ) + ); + break; + default: + break; + } + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.SignExtend( + 4, + il.Const( + 1, + insn->fields[1].value + ) + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + this->get_reg(il,insn->fields[2].value,4) + ) + ); + il.MarkLabel(end_tag); + } + } + break; + case N850_CMP: + { + il.AddInstruction( + il.Sub( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYOVSZ + + ) + ); + } + break; + case N850_CMPFS: + { + // TODO bit field specifications??? + switch (insn->fields[0].value) + { + case 0: // F + case 8: // SF + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_FPSR, + il.Const( + 4, + 0 + ) + ) + ); + break; + case 2: // EQ + case 3: // UQE + case 10: // SEQ + case 11: // NGL + condition = il.FloatCompareEqual( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4) + ); + + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_FPSR, + il.Const( + 4, + 1 + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_FPSR, + il.Const( + 4, + 0 + ) + ) + ); + il.MarkLabel(end_tag); + break; + case 4: // OLT + case 5: // ULT + case 12: // LT + case 13: // NGE + condition = il.FloatCompareLessThan( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4) + ); + + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_FPSR, + il.Const( + 4, + 1 + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_FPSR, + il.Const( + 4, + 0 + ) + ) + ); + il.MarkLabel(end_tag); + break; + case 6: // OLE + case 7: // ULE + case 14: // LE + case 15: // NGT + condition = il.FloatCompareLessEqual( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4) + ); + + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_FPSR, + il.Const( + 4, + 1 + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_FPSR, + il.Const( + 4, + 0 + ) + ) + ); + il.MarkLabel(end_tag); + break; + default: + il.AddInstruction(il.Unimplemented()); + break; + } + } + break; + case N850_CMPI: + { + il.AddInstruction( + il.Sub( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ), + FLAG_WRITE_CYOVSZ + + ) + ); + } + break; + case N850_CTRET: + { + il.AddInstruction(il.Return(NEC_SYSREG_CTPC)); + } + break; + case N850_CVTFHS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CVTFLS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CVTFSL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value, + il.FloatConvert( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_CVTFSH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CVTFSUL: + { + il.AddInstruction( + il.SetRegisterSplit( + 4, + insn->fields[1].value + 1, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_CVTFSUW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CVTFSW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CVTFULS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CVTFUWS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_CVTFWS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatConvert( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_DBRET: + { + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_PSW, + il.Register( + 4, + NEC_SYSREG_DBPSW + ) + ) + ); + il.AddInstruction(il.Return(NEC_SYSREG_DBPC)); + } + break; + case N850_DBTRAP: + { + il.AddInstruction( + il.Trap( + insn->fields[0].value + ) + ); + } + break; + case N850_DI: + { + // Intrinsics candidate + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + SYNC_EXCEPTIONS, + { } // Inputs + ) + ); + } + break; + case N850_DISPOSE: + { + il.SetRegister( + 4, + NEC_REG_SP, + il.Add( + 4, + il.Register(4, NEC_REG_SP), + il.Const( + 4, + insn->fields[1].value + ) + ) + + ); + for (int i = 0; i < 12; i++) + { + if (((0x800 >> i) & insn->fields[0].value) == (0x800 >> i)) { + il.AddInstruction( + il.SetRegister( + 4, + reg_list_regs[i], + il.Pop( + 4 + ) + ) + ); + } + } + + } + break; + case N850_DISPOSER: + { + il.SetRegister( + 4, + NEC_REG_SP, + il.Add( + 4, + il.Register(4, NEC_REG_SP), + il.Const( + 4, + insn->fields[1].value + ) + ) + + ); + for (int i = 0; i < 12; i++) + { + if (((0x800 >> i) & insn->fields[0].value) == (0x800 >> i)) { + il.AddInstruction( + il.SetRegister( + 4, + reg_list_regs[i], + il.Pop( + 4 + ) + ) + ); + } + } + il.AddInstruction( + il.Return( + this->get_reg(il,insn->fields[2].value,4) + ) + ); + } + break; + case N850_DIV: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.DivSigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ModSigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_DIVFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatDiv( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_DIVH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.DivSigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + this->get_reg(il,insn->fields[0].value,2) + ), + FLAG_WRITE_SZ + ) + ) + ); + } + break; + case N850_DIVHR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.DivSigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + this->get_reg(il,insn->fields[0].value,2) + ), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ModSigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + this->get_reg(il,insn->fields[0].value,2) + ) + ) + ) + ); + } + break; + case N850_DIVHU: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.DivUnsigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + this->get_reg(il,insn->fields[0].value,2) + ), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ModUnsigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + this->get_reg(il,insn->fields[0].value,2) + ) + ) + ) + ); + } + break; + case N850_DIVQ: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.DivSigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ModSigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_DIVQU: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.DivUnsigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ModUnsigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_DIVU: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.DivUnsigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ModUnsigned( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_EI: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + EI_INTRINSIC, + { } // Inputs + ) + ); + } + break; + case N850_EIRET: + { + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_PSW, + il.Register( + 4, + NEC_SYSREG_EIPSW + ) + ) + ); + il.AddInstruction(il.Return(il.Register(4,NEC_SYSREG_EIPC))); + + } + break; + case N850_FERET: + { + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_PSW, + il.Register( + 4, + NEC_SYSREG_FEPSW + ) + ) + ); + il.AddInstruction(il.Return(il.Register(4,NEC_SYSREG_FEPC))); + + } + break; + case N850_FETRAP: + { + il.AddInstruction( + il.Trap( + insn->fields[0].value + ) + ); + } + break; + case N850_FLOORFSL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value, + il.Floor( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_FLOORFSUL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value, + il.Floor( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_FLOORFSUW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Floor( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_FLOORFSW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Floor( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_FMAFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatAdd( + 4, + il.FloatMult( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ), + this->get_reg(il,insn->fields[2].value,4) + ) + ) + ); + } + break; + case N850_FMSFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatSub( + 4, + il.FloatMult( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ), + this->get_reg(il,insn->fields[2].value,4) + ) + ) + ); + } + break; + case N850_FNMAFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatNeg( + 4, + il.FloatAdd( + 4, + il.FloatMult( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ), + this->get_reg(il,insn->fields[2].value,4) + ) + ) + ) + ); + } + break; + case N850_FNMSFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatNeg( + 4, + il.FloatSub( + 4, + il.FloatMult( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ), + this->get_reg(il,insn->fields[2].value,4) + ) + ) + ) + ); + } + break; + case N850_HALT: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + SYNC_EXCEPTIONS, + { } // Inputs + ) + ); + } + break; + case N850_HSW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Or( + 4, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 16 + ) + ), + il.LogicalShiftRight( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 16 + ) + ) + ), + FLAG_WRITE_CYOVSZ + ) + ); + } + break; + case N850_HSH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYOVSZ + ) + ); + } + break; + case N850_JARL: + { + // TODO check + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Add( + 4, + this->get_reg(il,NEC_REG_PC,4), + il.Const( + 4, + 4 + ) + ) + + ) + ); + il.AddInstruction( + il.Call( + il.ConstPointer( + 4, + addr + insn->fields[0].value + ) + ) + ); + } + break; + case N850_JARL2: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Add( + 4, + this->get_reg(il,NEC_REG_PC,4), + il.Const( + 4, + 6 + ) + ) + + ) + ); + il.AddInstruction( + il.Call( + il.ConstPointer( + 4, + addr + insn->fields[0].value + ) + ) + ); + } + break; + case N850_JARL3: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Add( + 4, + this->get_reg(il,NEC_REG_PC,4), + il.Const( + 4, + 4 + ) + ) + + ) + ); + il.AddInstruction( + il.Call( + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_JMP: + { + if (insn->fields[0].value == NEC_REG_LP) { + il.AddInstruction(il.Return(il.Register(4,NEC_REG_LP))); + } else { + il.AddInstruction(il.Jump(il.Register(4, insn->fields[0].value))); + il.MarkLabel(false_tag); + } + } + break; + case N850_JMPI: + { + il.AddInstruction( + il.Jump( + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.Const( + 4, + insn->fields[0].value + ) + ) + ) + ); + } + break; + case N850_JR: + { + // TODO check + il.AddInstruction( + il.Jump( + il.Add( + 4, + il.Const( + 4, + addr + ), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + ) + ) + ) + ) + ); + } + break; + case N850_JRL: + { + il.AddInstruction( + il.Jump( + il.Add( + 4, + il.Const( + 4, + addr + ), + il.Const( + 4, + insn->fields[0].value + ) + ) + ) + ); + } + break; + case N850_LDBL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.SignExtend( + 4, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDBUL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ZeroExtend( + 4, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDDW: + { + // TODO check + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value + 1, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + ) + ) + ) + ) + ) + ); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + 4 + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDB: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.SignExtend( + 4, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDBU: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ZeroExtend( + 4, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.SignExtend( + 4, + il.Load( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDHU: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ZeroExtend( + 4, + il.Load( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Load( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDSR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_MOV: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_MOVI5: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.SignExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ) + ) + ); + } + break; + case N850_MOVI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Const( + 4, + insn->fields[0].value + ) + ) + ); + } + break; + case N850_MOVEA: + { + // 002106a2 + + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ) + ); + + } + break; + case N850_MOVHI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ShiftLeft( + 4, + il.Const( + 2, + insn->fields[0].value + ), + il.Const( + 4, + 16 + ) + ) + ) + ) + ); + } + break; + case N850_MAXFS: + { + condition = il.FloatCompareGreaterThan( + 4, + + this->get_reg(il,insn->fields[0].value,4), + this->get_reg(il,insn->fields[1].value,4) + ); + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + this->get_reg(il,insn->fields[0].value,4) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + this->get_reg(il,insn->fields[1].value,4) + ) + ); + il.MarkLabel(end_tag); + } + break; + case N850_MINFS: + { + condition = il.FloatCompareLessThan( + 4, + this->get_reg(il,insn->fields[0].value,4), + this->get_reg(il,insn->fields[1].value,4) + ); + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + this->get_reg(il,insn->fields[0].value,4) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + this->get_reg(il,insn->fields[1].value,4) + ) + ); + il.MarkLabel(end_tag); + } + break; + case N850_MULFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatMult( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_NEGFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatNeg( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_RECIPFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatDiv( + 4, + il.Const( + 4, + 1 + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_ROUNDFSL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value, + il.RoundToInt( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_ROUNDFSUL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value, + il.RoundToInt( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_ROUNDFSUW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.RoundToInt( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_ROUNDFSW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.RoundToInt( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_RSQRTFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatDiv( + 4, + il.Const( + 4, + 1 + ), + il.FloatSqrt( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ) + ); + } + break; + case N850_SQRTFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatSqrt( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_MUL: + { + il.AddInstruction( + il.SetRegisterSplit( + 4, + insn->fields[2].value, + insn->fields[1].value, + il.Mult( + 8, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_MULI: + { + il.AddInstruction( + il.SetRegisterSplit( + 4, + insn->fields[2].value, + insn->fields[1].value, + il.Mult( + 8, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + + ) + ) + ) + ); + } + break; + case N850_MULH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Mult( + 4, + this->get_reg(il,insn->fields[1].value,2), + this->get_reg(il,insn->fields[0].value,2) + ) + ) + ); + } + break; + case N850_MULHIMM: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Mult( + 4, + this->get_reg(il,insn->fields[1].value,2), + il.SignExtend( + 2, + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ) + ); + } + break; + case N850_MULHI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Mult( + 4, + this->get_reg(il,insn->fields[1].value,2), + il.Const( + 2, + insn->fields[0].value + ) + ) + ) + ); + } + break; + case N850_MULU: + { + il.AddInstruction( + il.SetRegisterSplit( + 4, + insn->fields[2].value, + insn->fields[1].value, + il.Mult( + 8, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_MULUI: + { + il.AddInstruction( + il.SetRegisterSplit( + 4, + insn->fields[2].value, + insn->fields[1].value, + il.Mult( + 8, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + + ) + ) + ) + ); + } + break; + case N850_NOP: + { + il.AddInstruction(il.Nop()); + } + break; + case N850_NOT: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Not( + 4, + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_NOT1: + { + il.AddInstruction( + il.Store( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ), + il.Xor( + 1, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ) + ), + il.Const( + 1, + (1 << insn->fields[0].value) & 0xff + ), + FLAG_WRITE_Z + ) + ) + ); + } + break; + case N850_NOT1R: + { + il.AddInstruction( + il.Store( + 1, + this->get_reg(il,insn->fields[1].value,4), + il.Xor( + 1, + il.Load( + 1, + this->get_reg(il,insn->fields[1].value,4) + ), + il.ShiftLeft( + 1, + il.Const( + 1, + 1 + ), + this->get_reg(il,insn->fields[0].value,1) + ), + FLAG_WRITE_Z + ) + ) + ); + } + break; + case N850_OR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Or( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_ORI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Or( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_PREPARE: + { + for (int i = 0; i < 12; i++) + { + if (((0x800 >> i) & insn->fields[0].value) == (0x800 >> i)) { + il.AddInstruction( + il.Push( + 4, + this->get_reg(il,reg_list_regs[i],4) + ) + ); + } + } + il.SetRegister( + 4, + NEC_REG_SP, + il.Sub( + 4, + il.Register(4, NEC_REG_SP), + il.Const( + 4, + insn->fields[1].value + ) + ) + + ); + // TODO need some example to verify + } + break; + case N850_RETI: + { + il.AddInstruction( + il.SetRegister( + 4, + NEC_SYSREG_PSW, + il.Register( + 4, + NEC_SYSREG_EIPSW + ) + ) + ); + il.AddInstruction( + il.Return( + il.Register( + 4, + NEC_SYSREG_EIPC + ) + ) + ); + } + break; + case N850_SAR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.ArithShiftRight( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_SARI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.ArithShiftRight( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_SARR: + { + // TODO test disassembly + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ArithShiftRight( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_SASF: + { + if (insn->fields[0].value == 5) { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Or( + 4, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.Const( + 4, + 1 + ) + ), + il.Const( + 4, + 1 + ) + ) + ) + ); + } else { + switch (insn->fields[0].value) + { + case 2: + condition = il.FlagCondition(LLFC_E); + break; + case 10: + condition = il.FlagCondition(LLFC_NE); + break; + case 11: + condition = il.FlagCondition(LLFC_UGT); + break; + case 3: + condition = il.FlagCondition(LLFC_ULE); + break; + case 0: + condition = il.FlagCondition(LLFC_O); + break; + case 8: + condition = il.FlagCondition(LLFC_NO); + break; + case 1: + condition = il.FlagCondition(LLFC_ULT); + break; + case 9: + condition = il.FlagCondition(LLFC_UGE); + break; + case 6: + condition = il.FlagCondition(LLFC_SLT); + break; + case 14: + condition = il.FlagCondition(LLFC_SGE); + break; + case 7: + condition = il.FlagCondition(LLFC_SLE); + break; + case 15: + condition = il.FlagCondition(LLFC_SGT); + break; + case 4: + condition = il.FlagCondition(LLFC_NEG); + break; + case 12: + condition = il.FlagCondition(LLFC_POS); + break; + case 13: + condition = il.CompareEqual( + 4, + il.Flag( + FLAG_SAT + ), + il.Const( + 4, + 1 + ) + ); + break; + default: + break; + } + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Or( + 4, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.Const( + 4, + 1 + ) + ), + il.Const( + 4, + 1 + ) + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.Const( + 4, + 1 + ) + ) + ) + ); + il.MarkLabel(end_tag); + } + + } + break; + case N850_SATADD: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_ALL + ) + ) + ); + } + break; + case N850_SATADDI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ), + FLAG_WRITE_ALL + ) + ) + ); + } + break; + case N850_SATSUB: + // TODO handle the saturation? + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_ALL + ) + ) + ); + } + break; + case N850_SATSUBI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ), + FLAG_WRITE_ALL + ) + ) + ); + } + break; + case N850_SATSUBR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[0].value,4), + this->get_reg(il,insn->fields[1].value,4), + FLAG_WRITE_ALL + ) + ) + ); + } + break; + case N850_SET1: + { + il.AddInstruction( + il.Store( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ), + il.Or( + 1, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ) + ), + il.Const( + 1, + (1 << insn->fields[0].value) & 0xff + ), + FLAG_WRITE_Z + ) + ) + ); + } + break; + case N850_SET1R: + { + il.AddInstruction( + il.Store( + 1, + this->get_reg(il,insn->fields[1].value,4), + il.Or( + 1, + il.Load( + 1, + this->get_reg(il,insn->fields[1].value,4) + ), + il.ShiftLeft( + 1, + il.Const( + 1, + 1 + ), + this->get_reg(il,insn->fields[0].value,4) + ), + FLAG_WRITE_Z + ) + ) + ); + } + break; + case N850_SETF: + { + if (insn->fields[0].value == 5) { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Const( + 4, + 1 + ) + ) + ); + } else { + switch (insn->fields[0].value) + { + case 2: + condition = il.FlagCondition(LLFC_E); + break; + case 10: + condition = il.FlagCondition(LLFC_NE); + break; + case 11: + condition = il.FlagCondition(LLFC_UGT); + break; + case 3: + condition = il.FlagCondition(LLFC_ULE); + break; + case 0: + condition = il.FlagCondition(LLFC_O); + break; + case 8: + condition = il.FlagCondition(LLFC_NO); + break; + case 1: + condition = il.FlagCondition(LLFC_ULT); + break; + case 9: + condition = il.FlagCondition(LLFC_UGE); + break; + case 6: + condition = il.FlagCondition(LLFC_SLT); + break; + case 14: + condition = il.FlagCondition(LLFC_SGE); + break; + case 7: + condition = il.FlagCondition(LLFC_SLE); + break; + case 15: + condition = il.FlagCondition(LLFC_SGT); + break; + case 4: + condition = il.FlagCondition(LLFC_NEG); + break; + case 12: + condition = il.FlagCondition(LLFC_POS); + break; + case 13: + condition = il.CompareEqual( + 4, + il.Flag( + FLAG_SAT + ), + il.Const( + 4, + 1 + ) + ); + break; + default: + break; + } + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Const( + 4, + 1 + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Const( + 4, + 0 + ) + ) + ); + il.MarkLabel(end_tag); + } + } + break; + case N850_SHL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_SHLI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_CY, + il.And( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.Const( + 4, + (0x80000000 >> (insn->fields[0].value - 1)) + ) + + ) + ) + ); + } + break; + case N850_SHR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.LogicalShiftRight( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_SHRI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_CY, + il.And( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.Const( + 4, + (1 << (insn->fields[0].value - 1)) + ) + + ) + ) + ); + } + break; + case N850_SLDB: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.SignExtend( + 4, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_SLDBU: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ZeroExtend( + 4, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_SLDH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.SignExtend( + 4, + il.Load( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_SLDHU: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ZeroExtend( + 4, + il.Load( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_SLDW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Load( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ) + ) + ) + ) + ); + } + break; + case N850_SSTB: + { + il.AddInstruction( + il.Store( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_SSTH: + { + il.AddInstruction( + il.Store( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_SSTW: + { + il.AddInstruction( + il.Store( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_STB: + { + il.AddInstruction( + il.Store( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_STH: + { + il.AddInstruction( + il.Store( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_STW: + { + il.AddInstruction( + il.Store( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_STSR: + { + // TODO test disass + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_SUB: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } + break; + case N850_SUBR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[0].value,4), + this->get_reg(il,insn->fields[1].value,4), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } + break; + case N850_SWITCH: + { + il.AddInstruction( + il.Jump( + il.Add( + 4, + il.Const( + 4, + addr + 2 + ), + il.SignExtend( + 4, + il.ShiftLeft( + 2, + il.Load( + 2, + il.Add( + 4, + il.Const( + 4, + addr + 2 + ), + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 1 + ) + ) + ) + ), + il.Const( + 4, + 1 + ) + ) + ) + ) + ) + ); + il.MarkLabel(end_tag); + } + break; + case N850_SXB: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[0].value, + il.SignExtend( + 4, + this->get_reg(il,insn->fields[0].value,1) + ) + ) + ); + } + break; + case N850_SXH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[0].value, + il.SignExtend( + 4, + this->get_reg(il,insn->fields[0].value,2) + ) + ) + ); + } + break; + case N850_SYNCE: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + SYNC_EXCEPTIONS, + { } // Inputs + ) + ); + } + break; + case N850_SYNCI: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + SYNC_INSN_FETCHER, + { } // Inputs + ) + ); + } + break; + case N850_SYNCM: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + SYNC_MEMORY_ACCESS, + { } // Inputs + ) + ); + } + break; + case N850_SYNCP: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + SYNC_PIPELINE, + { } // Inputs + ) + ); + } + break; + case N850_SYSCALL: + { + il.AddInstruction(il.SystemCall()); + } + break; + case N850_TRAP: + { + il.AddInstruction( + il.Trap( + insn->fields[0].value + ) + ); + } + break; + case N850_TST: + { + il.AddInstruction( + il.And( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_TST1: + { + il.AddInstruction( + + il.Add( + 1, + il.Load( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 2, + insn->fields[1].value + ) + ) + ) + ), + il.Const( + 1, + (1 << insn->fields[0].value) & 0xff + ), + FLAG_WRITE_Z + ) + + ); + } + break; + case N850_TST1R: + { + il.AddInstruction( + il.Or( + 1, + il.Load( + 1, + this->get_reg(il,insn->fields[1].value,4) + ), + il.ShiftLeft( + 1, + il.Const( + 1, + 1 + ), + this->get_reg(il,insn->fields[0].value,1) + ), + FLAG_WRITE_Z + ) + ); + } + break; + case N850_SUBFS: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.FloatSub( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + + ) + ) + ); + } + break; + case N850_TRFSR: + { + il.AddInstruction( + il.SetFlag( + FLAG_Z, + il.Register( + 4, + NEC_SYSREG_FPSR + ) + ) + ); + } + break; + case N850_TRNCFSL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value , + il.FloatTrunc( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_TRNCFSUL: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[1].value + 1, + insn->fields[1].value , + il.FloatTrunc( + 8, + this->get_reg(il,insn->fields[0].value,8) + ) + ) + ); + } + break; + case N850_TRNCFSUW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatTrunc( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_TRNCFSW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.FloatTrunc( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + ) + ); + } + break; + case N850_XOR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Xor( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_XORI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Xor( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 2, + insn->fields[0].value + ) + ), + FLAG_WRITE_SZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_ZXB: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[0].value, + il.ZeroExtend( + 4, + this->get_reg(il,insn->fields[0].value,1) + ) + ) + ); + } + break; + case N850_ZXH: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[0].value, + il.ZeroExtend( + 4, + this->get_reg(il,insn->fields[0].value,2) + ) + ) + ); + } + break; + case N850_LDLW: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[1].value, + il.Load( + 4, + this->get_reg(il,insn->fields[0].value,4) + ) + + ) + ); + } + break; + case N850_LOOP: + { + + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[0].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 1 + ), + FLAG_WRITE_CYOVSZ + ) + ) + ); + condition = il.CompareNotEqual( + 4, + this->get_reg(il,insn->fields[0].value,4), + il.Const( + 4, + 0 + ) + ); + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.Jump( + il.ConstPointer( + 4, + addr - insn->fields[1].value + ) + ) + ); + il.MarkLabel(false_tag); + + } + break; + case N850_MAC: + // TODO register splits verify + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[3].value + 1, + insn->fields[3].value, + il.Add( + 8, + il.Mult( + 8, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ), + il.RegisterSplit( + 8, + insn->fields[2].value + 1, + insn->fields[2].value + ) + ) + ) + ); + } + break; + case N850_MACU: + { + il.AddInstruction( + il.SetRegisterSplit( + 8, + insn->fields[3].value + 1, + insn->fields[3].value, + il.Add( + 8, + il.Mult( + 8, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ), + il.RegisterSplit( + 8, + insn->fields[2].value + 1, + insn->fields[2].value + ) + ) + ) + ); + } + break; + case N850_POPSP: + // TODO check + { + for (size_t i = insn->fields[1].value; i >= insn->fields[0].value; i--) + { + il.AddInstruction( + il.SetRegister( + 4, + i, + il.Pop( + 4 + ) + ) + ); + } + + } + break; + case N850_PUSHSP: + { + for (size_t i = insn->fields[1].value; i >= insn->fields[0].value; i--) + { + il.AddInstruction( + il.Push( + 4, + this->get_reg(il,i,4) + ) + ); + } + } + break; + case N850_RIEI: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + RIE_INTRINSIC, + { } // Inputs + ) + ); + } + break; + case N850_ROTL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.RotateLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } + break; + case N850_ROTLI: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.RotateLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.ZeroExtend( + 4, + il.Const( + 1, + insn->fields[0].value + ) + ), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } + break; + case N850_SATADDR: + { + // TODO saturation is not actually handled here + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_ALL + ) + ) + ); + } + break; + case N850_SATSUBL: + { + // TODO saturation is not actually handled here + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_ALL + ) + ) + ); + } + break; + case N850_SBF: + { + if (insn->fields[0].value == 5) { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Sub( + 4, + il.Sub( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4) + ), + il.Const( + 4, + 1 + ), + FLAG_WRITE_CYOVSZ + ) + ) + ); + } else { + switch (insn->fields[0].value) + { + case 2: + condition = il.FlagCondition(LLFC_E); + break; + case 10: + condition = il.FlagCondition(LLFC_NE); + break; + case 11: + condition = il.FlagCondition(LLFC_UGT); + break; + case 3: + condition = il.FlagCondition(LLFC_ULE); + break; + case 0: + condition = il.FlagCondition(LLFC_O); + break; + case 8: + condition = il.FlagCondition(LLFC_NO); + break; + case 1: + condition = il.FlagCondition(LLFC_ULT); + break; + case 9: + condition = il.FlagCondition(LLFC_UGE); + break; + case 6: + condition = il.FlagCondition(LLFC_SLT); + break; + case 14: + condition = il.FlagCondition(LLFC_SGE); + break; + case 7: + condition = il.FlagCondition(LLFC_SLE); + break; + case 15: + condition = il.FlagCondition(LLFC_SGT); + break; + case 4: + condition = il.FlagCondition(LLFC_NEG); + break; + case 12: + condition = il.FlagCondition(LLFC_POS); + break; + case 13: + condition = il.Unimplemented(); + break; + default: + break; + } + il.AddInstruction(il.If(condition,true_tag,false_tag)); + il.MarkLabel(true_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Sub( + 4, + il.Sub( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4) + ), + il.Const( + 4, + 1 + ), + FLAG_WRITE_CYOVSZ + ) + ) + ); + il.AddInstruction(il.Goto(end_tag)); + il.MarkLabel(false_tag); + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[3].value, + il.Sub( + 4, + this->get_reg(il,insn->fields[2].value,4), + this->get_reg(il,insn->fields[1].value,4), + FLAG_WRITE_CYOVSZ + ) + ) + ); + il.MarkLabel(end_tag); + } + } + break; + case N850_SCH0L: + { + // Count leading ones, candiadte for intrinsic + il.AddInstruction( + il.Intrinsic( + { RegisterOrFlag::Register(insn->fields[1].value) }, // Outputs + SCH0L_INTRINSIC, + { il.Register(4, insn->fields[0].value) } // Inputs + ) + ); + } + break; + case N850_SCH0R: + { + // Count trailing ones, candiadte for intrinsic + il.AddInstruction( + il.Intrinsic( + { RegisterOrFlag::Register(insn->fields[1].value) }, // Outputs + SCH0R_INTRINSIC, + { il.Register(4, insn->fields[0].value) } // Inputs + ) + ); + } + break; + case N850_SCH1L: + { + // Count leading zeros, candiadte for intrinsic + il.AddInstruction( + il.Intrinsic( + { RegisterOrFlag::Register(insn->fields[1].value) }, // Outputs + SCH1L_INTRINSIC, + { il.Register(4, insn->fields[0].value) } // Inputs + ) + ); + } + break; + case N850_SCH1R: + { + // Count trailing zeros, candiadte for intrinsic + il.AddInstruction( + il.Intrinsic( + { RegisterOrFlag::Register(insn->fields[1].value) }, // Outputs + SCH1R_INTRINSIC, + { il.Register(4, insn->fields[0].value) } // Inputs + ) + ); + } + break; + case N850_SHLL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ShiftLeft( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_SHRL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.LogicalShiftRight( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + case N850_SNOOZE: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + SNOOZE_INTRINSIC, + { } // Inputs + ) + ); + } + break; + case N850_STCW: + { + // TODO atomic operation not handled + il.AddInstruction( + il.Store( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_LDHL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.SignExtend( + 4, + il.Load( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDHUL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.ZeroExtend( + 4, + il.Load( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + ) + ) + ) + ) + ) + ) + ); + } + break; + case N850_LDWL: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.Load( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[1].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[0].value + ) + ) + ) + ) + ) + ); + } + break; + case N850_STDL: + { + il.AddInstruction( + il.Store( + 1, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,1) + ) + ); + } + break; + case N850_STDW: + { + il.AddInstruction( + il.Store( + 8, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[1].value + ) + ) + ), + il.RegisterSplit( + 8, + insn->fields[0].value + 1, + insn->fields[0].value + ) + ) + ); + } + break; + case N850_STHL: + { + il.AddInstruction( + il.Store( + 2, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,2) + ) + ); + } + break; + case N850_STWL: + { + il.AddInstruction( + il.Store( + 4, + il.Add( + 4, + this->get_reg(il,insn->fields[2].value,4), + il.SignExtend( + 4, + il.Const( + 3, + insn->fields[1].value + ) + ) + ), + this->get_reg(il,insn->fields[0].value,4) + ) + ); + } + break; + case N850_RIE: + { + il.AddInstruction( + il.Intrinsic( + { }, // Outputs + RIE_INTRINSIC, + { } // Inputs + ) + ); + } + break; + case N850_SHRR: + { + il.AddInstruction( + il.SetRegister( + 4, + insn->fields[2].value, + il.LogicalShiftRight( + 4, + this->get_reg(il,insn->fields[1].value,4), + this->get_reg(il,insn->fields[0].value,4), + FLAG_WRITE_CYSZ + ) + ) + ); + il.AddInstruction( + il.SetFlag( + FLAG_OV, + il.Const( + 4, + 0 + ) + ) + ); + } + break; + + default: + il.AddInstruction(il.Unimplemented()); + } + + free(insn); + return true; + } + free(insn); + return false; + /*if (addr == 0x000d0d0c) { + LogInfo("%s AT 0x%x: N: %d", insn->name, (uint32_t)addr,insn->n); + LogInfo("%s OP[0] type: %d: value: %d", insn->name, insn->fields[0].type,insn->fields[0].value); + LogInfo("%s OP[1] type: %d: value: %d", insn->name, insn->fields[1].type,insn->fields[1].value); + LogInfo("%s OP[2] type: %d: value: %d", insn->name, insn->fields[2].type,insn->fields[2].value); + }*/ + } + + virtual bool GetInstructionInfo(const uint8_t *data, uint64_t addr, size_t maxLen, InstructionInfo &result) override + { + insn_t *insn; + if ((insn = disassemble(data))) + { + result.length = insn->size; + uint32_t target; + switch (insn->op_type) + { + case OP_TYPE_JMP: + result.AddBranch(UnconditionalBranch, (insn->fields[0].value + (uint32_t)addr) & 0xffffffff); + break; + case OP_TYPE_LOOP: + target = ((uint32_t)addr - insn->fields[1].value) & 0xffffffff; + result.AddBranch(TrueBranch, target); // + (uint32_t) addr) & 0xffffffff); + result.AddBranch(FalseBranch, (insn->size + addr) & 0xffffffff); + break; + case OP_TYPE_CJMP: + target = (insn->fields[0].value + (uint32_t)addr) & 0xffffffff; + if (insn->fields[0].type == TYPE_JMP) + { + result.AddBranch(TrueBranch, target); // + (uint32_t) addr) & 0xffffffff); + result.AddBranch(FalseBranch, (insn->size + addr) & 0xffffffff); + } + else + { + // LogInfo("CJMP WENT WRONG AT 0x%x", addr); + free(insn); + return false; + } + break; + case OP_TYPE_CALL: + target = (insn->fields[0].value + (uint32_t)addr) & 0xffffffff; + if (target != ((uint32_t)addr + insn->size)) + result.AddBranch(CallDestination, target); // + (uint32_t) addr) & 0xffffffff); + break; + case OP_TYPE_RCALL: + result.AddBranch(IndirectBranch); + break; + case OP_TYPE_RJMP: + result.AddBranch(IndirectBranch); + break; + case OP_TYPE_RET: + result.AddBranch(FunctionReturn); + break; + case OP_TYPE_TRAP: + result.AddBranch(FunctionReturn); + break; + default: + break; + } + free(insn); + return true; + } + free(insn); + return false; + } + + virtual bool GetInstructionText(const uint8_t *data, uint64_t addr, size_t &len, std::vector &result) override + { + insn_t *insn; + char tmp[256] = {0}; + if ((insn = disassemble(data))) + { + + int name_len = strlen(insn->name); + for (int i = name_len; i < 14; i++) + { + tmp[i - name_len] = ' '; + } + len = insn->size; + tmp[14 - name_len] = 0; + result.emplace_back(InstructionToken, insn->name); + result.emplace_back(TextToken, tmp); + char hex_val[20] = {0}; + char reg_str[10] = {0}; + for (int op_index = 0; op_index < insn->n; op_index++) + { + switch (insn->fields[op_index].type) + { + case TYPE_REG: + result.emplace_back(RegisterToken, reg_name[insn->fields[op_index].value]); + break; + case TYPE_REG_MEM: + if (op_index > 0) + result.pop_back(); + snprintf(reg_str, 10, "[%s]", reg_name[insn->fields[op_index].value]); + result.emplace_back(RegisterToken, reg_str); + break; + case TYPE_MEM: + if (insn->fields[op_index].value == 0) + break; + if (insn->fields[op_index].sign) + snprintf(hex_val, 20, "%s0x%x", ((int32_t)insn->fields[op_index].value < 0) ? "-" : "", ((int32_t)insn->fields[op_index].value < 0) ? -(int32_t)insn->fields[op_index].value : (int32_t)insn->fields[op_index].value); + else + snprintf(hex_val, 20, "0x%x", (uint32_t)insn->fields[op_index].value); + result.emplace_back(IntegerToken, hex_val, insn->fields[op_index].value); + break; + case TYPE_IMM: + if (insn->fields[op_index].sign) + snprintf(hex_val, 20, "%s0x%x", ((int32_t)insn->fields[op_index].value < 0) ? "-" : "", ((int32_t)insn->fields[op_index].value < 0) ? -(int32_t)insn->fields[op_index].value : (int32_t)insn->fields[op_index].value); + else + snprintf(hex_val, 20, "0x%x", (uint32_t)insn->fields[op_index].value); + result.emplace_back(IntegerToken, hex_val, insn->fields[op_index].value); + break; + case TYPE_JMP: + snprintf(hex_val, 20, "0x%x", (uint32_t)(insn->fields[op_index].value) + (uint32_t)addr); // + (uint32_t) addr)); + result.emplace_back(IntegerToken, hex_val, insn->fields[op_index].value + addr); + break; + case TYPE_LOOP: + snprintf(hex_val, 20, "0x%x", (uint32_t)addr - (uint32_t)(insn->fields[op_index].value)); // + (uint32_t) addr)); + result.emplace_back(IntegerToken, hex_val, addr - insn->fields[op_index].value); + break; + case TYPE_CCCC: + result.emplace_back(RegisterToken, cccc_name[insn->fields[op_index].value]); + break; + case TYPE_COND: + result.emplace_back(RegisterToken, cond_name[insn->fields[op_index].value]); + break; + case TYPE_SYSREG: + result.emplace_back(RegisterToken, this->GetSysregName(insn->fields[op_index].value)); + break; + case TYPE_LIST: + result.emplace_back(OperandSeparatorToken, "{"); + for (int i = 0; i < 12; i++) + { + if (((0x800 >> i) & insn->fields[op_index].value) == (0x800 >> i)) { + result.emplace_back(RegisterToken, reg_list_names[i]); + result.emplace_back(OperandSeparatorToken, ", "); + } + } + result.pop_back(); + result.emplace_back(OperandSeparatorToken, "}"); + default: + break; + } + result.emplace_back(OperandSeparatorToken, ", "); + } + result.pop_back(); + free(insn); + return true; + } + free(insn); + return false; + } +}; + +class Nec850CallingConvention : public CallingConvention +{ +public: + Nec850CallingConvention(Architecture *arch) : CallingConvention(arch, "default") + { + } + + virtual vector GetIntegerArgumentRegisters() override + { + return vector{ + NEC_REG_R6, NEC_REG_R7, NEC_REG_R8, NEC_REG_R9}; + } + + virtual uint32_t GetIntegerReturnValueRegister() override + { + return NEC_REG_R10; + } + + virtual vector GetCallerSavedRegisters() override + { + return vector{ + NEC_REG_R10, NEC_REG_R11, NEC_REG_R12, NEC_REG_R13, NEC_REG_R14, NEC_REG_R15, NEC_REG_R16, NEC_REG_R17, NEC_REG_R18, NEC_REG_R19}; + } + + virtual vector GetCalleeSavedRegisters() override + { + return vector{ + NEC_REG_R25, NEC_REG_R25, NEC_REG_R27, NEC_REG_R28, NEC_REG_EP, NEC_REG_LP}; + } +}; +extern "C" +{ + BN_DECLARE_CORE_ABI_VERSION + + BINARYNINJAPLUGIN void CorePluginDependencies() + { + AddOptionalPluginDependency("view_elf"); + AddOptionalPluginDependency("view_macho"); + AddOptionalPluginDependency("view_pe"); + } + + BINARYNINJAPLUGIN bool CorePluginInit() + { + + /* create, register arch in global list of available architectures */ + Architecture *nec850 = new NEC850("nec850"); + Architecture::Register(nec850); + Ref conv; + conv = new Nec850CallingConvention(nec850); + nec850->RegisterCallingConvention(conv); + nec850->SetDefaultCallingConvention(conv); + +#define EM_NEC850 87 + BinaryViewType::RegisterArchitecture( + "ELF", + EM_NEC850, + LittleEndian, + nec850); +#define EM_NECV850 36 + BinaryViewType::RegisterArchitecture( + "ELF", + EM_NECV850, + LittleEndian, + nec850); + + return true; + } +} +/* +extern "C" +{ + BN_DECLARE_CORE_ABI_VERSION + + BINARYNINJAPLUGIN bool CorePluginInit() + { + PluginCommand::Register("Test Plugin\\Test", "It's a test action!", [](BinaryView* view) { + for (auto& symbol: view->GetSymbols()) + { + LogInfo("%s", symbol->GetFullName().c_str()); + } + }); + return true; + } + + BINARYNINJAPLUGIN void CorePluginDependencies() + { + } +} +*/ diff --git a/nec850.h b/nec850.h new file mode 100644 index 0000000..50894fb --- /dev/null +++ b/nec850.h @@ -0,0 +1,148 @@ +// MIT License +// +// Copyright (c) 2015-2024 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef TESTPLUGIN_LIBRARY_H +#define TESTPLUGIN_LIBRARY_H + +#include "binaryninjaapi.h" + +#endif //TESTPLUGIN_LIBRARY_H +#define NEC_REG_R0 0 +#define NEC_REG_R1 1 +#define NEC_REG_R2 2 +#define NEC_REG_SP 3 +#define NEC_REG_R4 4 +#define NEC_REG_R5 5 +#define NEC_REG_R6 6 +#define NEC_REG_R7 7 +#define NEC_REG_R8 8 +#define NEC_REG_R9 9 +#define NEC_REG_R10 10 +#define NEC_REG_R11 11 +#define NEC_REG_R12 12 +#define NEC_REG_R13 13 +#define NEC_REG_R14 14 +#define NEC_REG_R15 15 +#define NEC_REG_R16 16 +#define NEC_REG_R17 17 +#define NEC_REG_R18 18 +#define NEC_REG_R19 19 +#define NEC_REG_R20 20 +#define NEC_REG_R21 21 +#define NEC_REG_R22 22 +#define NEC_REG_R23 23 +#define NEC_REG_R24 24 +#define NEC_REG_R25 25 +#define NEC_REG_R26 26 +#define NEC_REG_R27 27 +#define NEC_REG_R28 28 +#define NEC_REG_R29 29 +#define NEC_REG_EP 30 +#define NEC_REG_LP 31 +#define NEC_REG_PC 32 + + +// regId + 40 * sellID +#define NEC_SYSREG_EIPC 100 +#define NEC_SYSREG_EIPSW 101 +#define NEC_SYSREG_FEPC 102 +#define NEC_SYSREG_FEPSW 103 +#define NEC_SYSREG_PSW 105 +#define NEC_SYSREG_FPSR 106 +#define NEC_SYSREG_FPEPC 107 +#define NEC_SYSREG_FPST 108 +#define NEC_SYSREG_FPCC 109 +#define NEC_SYSREG_FPCFG 110 +#define NEC_SYSREG_FPEC 111 +#define NEC_SYSREG_EIIC 113 +#define NEC_SYSREG_FEIC 114 +#define NEC_SYSREG_CTPC 116 +#define NEC_SYSREG_CTPSW 117 +#define NEC_SYSREG_DBPC 118 +#define NEC_SYSREG_DBPSW 119 +#define NEC_SYSREG_CTBP 120 +#define NEC_SYSREG_EIWR 128 +#define NEC_SYSREG_FEWR 129 +#define NEC_SYSREG_BSEL 131 +#define NEC_SYSREG_MCFG0 140 +#define NEC_SYSREG_RBASE 142 +#define NEC_SYSREG_EBASE 143 +#define NEC_SYSREG_INTBP 144 +#define NEC_SYSREG_MCTL 145 +#define NEC_SYSREG_PID 146 +#define NEC_SYSREG_SCCFG 151 +#define NEC_SYSREG_SCBP 152 +#define NEC_SYSREG_HTCFG0 180 +#define NEC_SYSREG_MEA 186 +#define NEC_SYSREG_ASID 187 +#define NEC_SYSREG_MEI 188 + + +#define FLAG_SAT 0 +#define FLAG_CY 1 +#define FLAG_OV 2 +#define FLAG_S 3 +#define FLAG_Z 4 + +#define FLAG_WRITE_NONE 5 +#define FLAG_WRITE_ALL 6 +#define FLAG_WRITE_OVSZ 7 +#define FLAG_WRITE_CYOVSZ 8 +#define FLAG_WRITE_Z 9 +#define FLAG_WRITE_SZ 10 +#define FLAG_WRITE_CYSZ 11 + +enum cond { + NEC850_CCCC_V = 0, + NEC850_CCCC_NV = 8, + NEC850_CCCC_CL = 1, + NEC850_CCCC_NCNL = 9, + NEC850_CCCC_Z = 2, + NEC850_CCCC_NZ = 10, + NEC850_CCCC_NH = 3, + NEC850_CCCC_H = 11, + NEC850_CCCC_SN = 4, + NEC850_CCCC_NSP = 12, + NEC850_CCCC_T = 5, + NEC850_CCCC_LT = 6, + NEC850_CCCC_GE = 14, + NEC850_CCCC_LE = 7, + NEC850_CCCC_GT = 15, + +}; + +enum VLEIntrinsics{ + SCH1L_INTRINSIC, + SCH1R_INTRINSIC, + SCH0L_INTRINSIC, + SCH0R_INTRINSIC, + SYNC_MEMORY_ACCESS, + SYNC_PIPELINE, + SYNC_INSN_FETCHER, + SYNC_EXCEPTIONS, + CLL_INTRINSIC, + SNOOZE_INTRINSIC, + DI_INTRINSIC, + EI_INTRINSIC, + HALT_INTRINSIC, + RIE_INTRINSIC +}; diff --git a/plugin.json b/plugin.json new file mode 100644 index 0000000..a42b189 --- /dev/null +++ b/plugin.json @@ -0,0 +1,27 @@ +{ + "pluginmetadataversion" : 2, + "name": "NEC850 Architecture", + "type": ["architecture"], + "api": ["C++"], + "description": "Architecture plugin for Renesas RH850/V850 family of processors.", + "longdescription": "This Binary Ninja plugin provides a native implemantion for the Renesas RH850/V850 architectue. The main reason for writing this from scratch instead of using existing plugin is that any Architecture plugin wirtten in Python is not usable for large binaries as the analysis takes ages. Therefore, this is a complete coverage of this architecture wirtten purely in C/C++.", + "license": { + "name": "Apache-2.0", + "text": "Copyright 2024 Accenture\n\nLicensed 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\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless 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." + }, + "platforms" : ["Darwin", "Linux", "Windows"], + "installinstructions" : { + "Darwin" : "N/A", + "Linux" : "N/A", + "Windows" : "N/A" + }, + "dependencies": { + "pip": [], + "apt": [], + "installers": [], + "other": [] + }, + "version": "1.0", + "author": "Accenture (Martin Petran)", + "minimumbinaryninjaversion": 4333 +} \ No newline at end of file diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..7edf63d --- /dev/null +++ b/shell.nix @@ -0,0 +1,8 @@ +{ pkgs ? import {} }: + pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + cmake + clang + darwin.apple_sdk.frameworks.CoreServices + ]; +} \ No newline at end of file