├── .allstar └── binary_artifacts.yaml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cmake ├── Findgflags.cmake └── clang_overrides.cmake ├── docs ├── design.md ├── images │ ├── components.png │ ├── screenshot1.png │ └── screenshot2.png └── setup.md ├── plugin ├── CMakeLists.txt ├── arch_hexagon.cc ├── decoder.cc ├── decoder.h ├── decoder_test.cc ├── gen_il_funcs.py ├── gen_il_funcs_data.py ├── gen_il_funcs_test.py ├── gen_insn_text_funcs.py ├── gen_insn_text_funcs_test.py ├── hex_regs.h ├── il_util.cc ├── il_util.h ├── il_util_test.cc ├── insn_util.cc ├── insn_util.h ├── insn_util_test.cc ├── packet_context.cc ├── packet_context.h ├── packet_db.cc ├── packet_db.h ├── packet_db_test.cc ├── relocs.h ├── status_macros.h ├── status_matchers.h ├── text_util.cc ├── text_util.h └── type_util.py ├── requirements.txt ├── scripts ├── CMakeLists.txt └── bn_disasm.py.in ├── test_binaries ├── CMakeLists.txt ├── bn_hlil_test.py ├── bn_hlil_test_app.c ├── bn_llil_test.py ├── bn_llil_test_app.s ├── build_hlil_test.dockerfile ├── build_hlil_test.makefile ├── build_llil_test.dockerfile ├── build_llil_test.makefile ├── first.s └── prebuilt │ ├── bn_hlil_test_app │ └── bn_llil_test_app └── third_party ├── chromium ├── CMakeLists.txt ├── LICENSE └── blink │ ├── CMakeLists.txt │ ├── interval_map.h │ └── interval_map_unittest.cc ├── gflags_CMakeLists.txt.in └── qemu-hexagon ├── CMakeLists.txt ├── LICENSE ├── README.md ├── attribs.h ├── attribs_def.h ├── bitmap.h ├── bitops.h ├── cpu_bits.h ├── decode.c ├── decode.h ├── decode_ext_mmvec.c ├── decode_ext_mmvec.h ├── dectree.py ├── gen_dectree_import.c ├── gen_op_attribs.py ├── gen_op_regs.py ├── gen_opcodes_def.py ├── gen_semantics.c ├── gen_shortcode.py ├── hex_common.py ├── iclass.c ├── iclass.h ├── imported ├── allext.idef ├── allext_macros.def ├── allextenc.def ├── allidefs.def ├── alu.idef ├── branch.idef ├── compare.idef ├── encode.def ├── encode_pp.def ├── encode_subinsn.def ├── float.idef ├── iclass.def ├── ldst.idef ├── macros.def ├── mmvec │ ├── encode_ext.def │ ├── ext.idef │ └── macros.def ├── mpy.idef ├── shift.idef ├── subinsns.idef └── system.idef ├── insn.h ├── mmvec.h ├── opcodes.c ├── opcodes.h ├── q6v_decode.c ├── reg_fields.c ├── reg_fields.h └── reg_fields_def.h /.allstar/binary_artifacts.yaml: -------------------------------------------------------------------------------- 1 | # Exemption reason: Binary artifacts under test_binaries/ are used for unit-testing. Source is included with reproducible build. Binaries are reviewable using binja-hexagon ;-P 2 | # Exemption timeframe: permanent 3 | optConfig: 4 | optOut: true 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.pyc 3 | tags 4 | cscope.* 5 | .clangd/ 6 | .cache/ 7 | compile_commands.json 8 | build/ 9 | *.idb 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third_party/binaryninja-api"] 2 | path = third_party/binaryninja-api 3 | url = https://github.com/Vector35/binaryninja-api 4 | branch = master 5 | [submodule "third_party/googletest"] 6 | path = third_party/googletest 7 | url = https://github.com/google/googletest.git 8 | [submodule "third_party/abseil-cpp"] 9 | path = third_party/abseil-cpp 10 | url = https://github.com/abseil/abseil-cpp.git 11 | [submodule "third_party/gflags"] 12 | path = third_party/gflags 13 | url = https://github.com/gflags/gflags.git 14 | [submodule "third_party/glog"] 15 | path = third_party/glog 16 | url = https://github.com/google/glog.git 17 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Google LLC 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along 14 | # with this program; if not, write to the Free Software Foundation, Inc., 15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | # 17 | cmake_minimum_required (VERSION 3.0) 18 | project ("binja-hexagon" C CXX ASM) 19 | set(CMAKE_CXX_STANDARD 17) 20 | 21 | # Set default build type. 22 | if(NOT CMAKE_BUILD_TYPE) 23 | message(STATUS "Setting build type to 'Release' as none was specified.") 24 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING 25 | "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." 26 | FORCE) 27 | endif() 28 | 29 | SET( CMAKE_EXPORT_COMPILE_COMMANDS ON ) 30 | 31 | add_custom_target( 32 | copy-compile-commands ALL 33 | ${CMAKE_COMMAND} -E copy_if_different 34 | ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json 35 | ${CMAKE_SOURCE_DIR}/compile_commands.json 36 | ) 37 | 38 | # Binary Ninja plugins require "-fPIC". 39 | set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) 40 | 41 | option(USE_DOCKER_BUILD 42 | "If ON, cross-builds Hexagon targets using a docker image from QEMU's registry" OFF) 43 | 44 | # Enable testing. 45 | enable_testing() 46 | add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) 47 | 48 | # 49 | # Build gflags at configure time. 50 | # 51 | configure_file(third_party/gflags_CMakeLists.txt.in 52 | gflags-build/CMakeLists.txt) 53 | execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . 54 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/gflags-build ) 55 | execute_process(COMMAND ${CMAKE_COMMAND} --build . --target all 56 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/gflags-build ) 57 | 58 | list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 59 | find_package(gflags REQUIRED) 60 | 61 | # 62 | # third_party dependencies. 63 | # 64 | option(BUILD_TESTING OFF) 65 | option(WITH_UNWIND OFF) 66 | option(BENCHMARK_ENABLE_TESTING OFF) 67 | option(ABSL_USE_EXTERNAL_GOOGLETEST ON) 68 | SET(HEADLESS ON) 69 | add_subdirectory(third_party/glog EXCLUDE_FROM_ALL) 70 | add_subdirectory(third_party/googletest EXCLUDE_FROM_ALL) 71 | add_subdirectory(third_party/abseil-cpp EXCLUDE_FROM_ALL) 72 | add_subdirectory(third_party/chromium EXCLUDE_FROM_ALL) 73 | add_subdirectory(third_party/binaryninja-api EXCLUDE_FROM_ALL) 74 | 75 | # 76 | # Plugin project. 77 | # 78 | include_directories(${CMAKE_SOURCE_DIR}) 79 | add_subdirectory(scripts) 80 | add_subdirectory(test_binaries) 81 | add_subdirectory(third_party/qemu-hexagon) 82 | add_subdirectory(plugin) 83 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows 28 | [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Binary Ninja Hexagon Processor Plugin 2 | 3 | ## Overview 4 | 5 | This is a new architecture plugin for [Binary Ninja](https://binary.ninja/) 6 | reverse engineering platform. It adds support for Qualcomm's 7 | [Hexagon CPUs](https://en.wikipedia.org/wiki/Qualcomm_Hexagon). 8 | 9 | Main features: 10 | 11 | 1. **Complete disassembler support**. Plugin decodes individual instructions, 12 | parses and tokenizes instruction operands, and populates branch information 13 | for all packets: 14 | 15 | ![Screenshot1](/docs/images/screenshot1.png) 16 | 17 | 1. **Partial decompiler support**. Plugin lifts (a subset of) Hexagon 18 | instructions to Binary Ninja's 19 | [Low-Level Intermediate Language](https://docs.binary.ninja/dev/bnil-llil.html) 20 | (LLIL). Lifter manages clobbered registers, implements ".new" semantics and 21 | packet level branch semantics. Thanks to BN's IL modules, the LLIL 22 | representation is lifted to pseudo-C, High-Level IL (HLIL), producing 23 | readable, decompiled code: 24 | 25 | ![Screenshot2](/docs/images/screenshot2.png) 26 | 27 | ## Additional Information 28 | 29 | * [Setup and build](/docs/setup.md) instructions. 30 | 31 | * [High level design](/docs/design.md) document. 32 | 33 | ## Status 34 | 35 | The plugin is very much in Alpha stage. Only around 40% of Hexagon's > 2000 36 | instructions are currently lifted to LLIL. Feedback, bug reports and PRs are 37 | welcome. 38 | 39 | ## Acknowledgments 40 | 41 | This plugin was built using 42 | [QEMU's Hexagon target](https://github.com/quic/qemu) by Taylor Simpson from 43 | Qualcomm Innovation Center. 44 | 45 | Instruction lifters are [auto generated](/plugin/gen_il_funcs.py) by parsing 46 | semantics descriptions. These descriptions are preprocessed using 47 | [PCPP](https://github.com/ned14/pcpp) by Niall Douglas and David Beazley, and 48 | parsed using [Lark-parser](https://github.com/lark-parser/lark) by Erez Shinan. 49 | 50 | ## License 51 | 52 | This project is a derivative work of QEMU's Hexagon target, therefore, it is 53 | licensed under GPLv2, as the original work. 54 | 55 | -------------------------------------------------------------------------------- /cmake/Findgflags.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Google LLC 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along 14 | # with this program; if not, write to the Free Software Foundation, Inc., 15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | # 17 | include(${CMAKE_BINARY_DIR}/gflags-build/build/gflags-config.cmake) 18 | set(gflags_FOUND TRUE) 19 | -------------------------------------------------------------------------------- /cmake/clang_overrides.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Google LLC 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along 14 | # with this program; if not, write to the Free Software Foundation, Inc., 15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | # 17 | set(CMAKE_C_FLAGS "-Wall -std=gnu99") 18 | set(CMAKE_C_FLAGS_DEBUG "-g") 19 | set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG") 20 | set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") 21 | set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g") 22 | 23 | set(CMAKE_CXX_FLAGS "-Wall") 24 | set(CMAKE_CXX_FLAGS_DEBUG "-g") 25 | set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") 26 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") 27 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") 28 | -------------------------------------------------------------------------------- /docs/design.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | Hexagon CPU 4 | [design](https://developer.qualcomm.com/software/hexagon-dsp-sdk/dsp-processor) 5 | presents several, unique, challenges to a reverse engineer: 6 | 7 | 1. **Scale**: with scalar and vector extensions, Hexagon has more than 2000 8 | distinct instructions. 9 | 10 | 2. **Multi-threading**: with four execution slots, this CPU is inherently 11 | multi-threaded. Instructions are groups in *packets*, where each packet has 12 | up to four instructions that run in parallel. 13 | 14 | 3. **Data dependencies**: instructions in a given packet can reference data 15 | produced by other instructions in the same packet. This *".new"* register 16 | semantics is unique to this variable length instruction CPU. 17 | 18 | 4. **Branch semantics**: a packet can have up to two branch instructions. There 19 | are many branch types: direct vs indirect, conditional vs unconditional and 20 | jump vs call. Modeling this unique branch semantics is rather challenging: 21 | only a single branch may be taken at the end of packet processing, subject 22 | to some ordering rules. 23 | 24 | -------------------------------------------------------------------------------- 25 | 26 | The way this plugin tackles the complexity described above is through automatic 27 | code generation. The plugin has build-time components that parse instruction 28 | descriptors, and automatically generate the LLIL lifting code. At runtime, the 29 | plugin has components that track packet level data, implement the ".new" and 30 | branch semantics. 31 | 32 | ## Components 33 | 34 | ![Components](/docs/images/components.png) 35 | 36 | (Read from top to bottom, left to right). 37 | 38 | * **Instruction definitions**: a dataset that describes instructions encoding, 39 | behavior and semantics. This is part of QEMU's Hexagon target code base, 40 | located at `third_party/qemu-hexagon/`. For example, 41 | [alu.idef](/third_party/qemu-hexagon/imported/alu.idef) has the following 42 | description for the `A2_add` instruction: 43 | 44 | ``` 45 | Q6INSN(A2_add,"Rd32=add(Rs32,Rt32)",ATTRIBS(), 46 | "Add 32-bit registers", 47 | { RdV=RsV+RtV;}) 48 | ``` 49 | 50 | * **Instruction attributes**: a data structure that holds instruction 51 | attributes, available to C programs. These header files are generated by a 52 | set of scripts in `/third_party/qemu_hexagon/`, and consumed at runtime by 53 | the instruction [decoder](/third_party/qemu-hexagon/decode.c). 54 | 55 | * **Decoder**: decodes a vector of 32b words to a sequence of Hexagon 56 | instructions, grouped in a single packet. Decoder fails safe when it cannot 57 | decode a given input. Decoder fills the following information for each 58 | [instruction](/third_party/qemu-hexagon/insn.h): instruction id (or tag), 59 | operands information (immediate values or registers). 60 | 61 | * **Instruction Text Tokens Generator**: 62 | [gen_insn_text_funcs.py](/plugin/gen_insn_text_funcs.py) parses instruction 63 | definitions, and generates code that implements BN's 64 | [GetInstructionText](https://api.binary.ninja/binaryninja.architecture-module.html?highlight=text#binaryninja.architecture.Architecture.get_instruction_text) 65 | API for each instruction. This works by parsing the *behavior descriptor* 66 | using a grammar, then transforming the resulting tree into a sequence of 67 | `BinaryNinja::InstructionTextToken`s. For example, `A2_add` has the 68 | following descriptor "Rd32=add(Rs32,Rt32)". This is parsed into tree: 69 | 70 | ``` 71 | assign_to_op 72 | reg 73 | Rd32 74 | ... 75 | call_exp 76 | ... 77 | call2 78 | insn add 79 | reg 80 | Rs32 81 | reg 82 | Rt32 83 | ``` 84 | 85 | and transformed into the following sequence of tokens: 86 | 87 | ``` 88 | void tokenize_A2_add(uint64_t pc, const Packet &pkt, const Insn &insn, 89 | std::vector &result) { 90 | result.emplace_back(RegisterToken, StrCat("R", insn.regno[0])); 91 | result.emplace_back(TextToken, " = "); 92 | result.emplace_back(InstructionToken, "add"); 93 | result.emplace_back(TextToken, "("); 94 | result.emplace_back(RegisterToken, StrCat("R", insn.regno[1])); 95 | result.emplace_back(TextToken, ","); 96 | result.emplace_back(RegisterToken, StrCat("R", insn.regno[2])); 97 | result.emplace_back(TextToken, ")"); 98 | } 99 | ``` 100 | 101 | * **Instruction Utils**: this module implements BN's 102 | [GetInstructionText](https://api.binary.ninja/binaryninja.architecture-module.html?highlight=text#binaryninja.architecture.Architecture.get_instruction_text) 103 | API by calling the generated instruction tokenizers. In addition, it 104 | implements BN's 105 | [GenInstructionInfo](https://api.binary.ninja/binaryninja.architecture-module.html?highlight=text#binaryninja.architecture.Architecture.get_instruction_info) 106 | API: it analyzes decoder's information, and reports packet's branch targets. 107 | 108 | * **Packet Database**: maps binary addresses to instruction packets. 109 | BinaryNinja works at a single instruction level, however, in order to 110 | properly model an instruction, knowledge on its neighboring packet 111 | instructions is needed. 112 | 113 | * **Instruction IL Generator**: [gen_il_funcs.py](/plugin/gen_il_funcs.py) 114 | parses instruction definitions, and generated code that implements BN's 115 | [GetInstructionLowLevelIL](https://api.binary.ninja/binaryninja.architecture-module.html?highlight=text#binaryninja.architecture.Architecture.get_instruction_low_level_il) 116 | API for each (supported) instruction. This works by parsing the *semantics 117 | descriptor* using a C-like grammar, then transforming the resulting tree 118 | into a sequence of operations on `BinaryNinja::LowLevelILFunction` object. 119 | This builds an equivalent symbolic model, and effectively *lifts* the 120 | instruction. For example, `A2_add` has the following descriptor "{ 121 | RdV=RsV+RtV;}". This C-code is parsed into tree: 122 | 123 | ``` 124 | multi_stmt 125 | assg_stmt 126 | assg 127 | RdV 128 | expr_binop 129 | RsV 130 | + 131 | RtV 132 | ``` 133 | 134 | and transformed into the following sequence of operations: 135 | 136 | ``` 137 | void lift_A2_add(Architecture *arch, uint64_t pc, const Packet &pkt, 138 | const Insn &insn, int insn_num, PacketContext &ctx) { 139 | LowLevelILFunction &il = ctx.IL(); 140 | const int RdV = ctx.AddDestWriteOnlyReg(MapRegNum('R', insn.regno[0])); 141 | const int RsV = MapRegNum('R', insn.regno[1]); 142 | const int RtV = MapRegNum('R', insn.regno[2]); 143 | il.AddInstruction(il.SetRegister( 144 | 4, RdV, il.Add(4, il.Register(4, RsV), il.Register(4, RtV)))); 145 | } 146 | ``` 147 | 148 | A more involved example is `A2_pxort` instruction. It has the following 149 | semantics: 150 | 151 | ``` 152 | SEMANTICS( \ 153 | "A2_pxort", \ 154 | "if (Pu4) ""Rd32=xor(Rs32,Rt32)", \ 155 | """{if(fLSBOLD(PuV)){RdV=RsV^RtV;} else {CANCEL;}}""" \ 156 | ) 157 | ``` 158 | 159 | This is modeled using IL 160 | ["if" statements](https://api.binary.ninja/binaryninja.lowlevelil-module.html#binaryninja.lowlevelil.LowLevelILFunction.if_expr): 161 | 162 | ``` 163 | void lift_A2_pxort(Architecture *arch, uint64_t pc, const Packet &pkt, 164 | const Insn &insn, int insn_num, PacketContext &ctx) { 165 | LowLevelILFunction &il = ctx.IL(); 166 | const int PuV = MapRegNum('P', insn.regno[0]); 167 | const int RdV = ctx.AddDestWriteOnlyReg(MapRegNum('R', insn.regno[1])); 168 | const int RsV = MapRegNum('R', insn.regno[2]); 169 | const int RtV = MapRegNum('R', insn.regno[3]); 170 | { 171 | LowLevelILLabel true_case, done; 172 | il.AddInstruction(il.If(il.Register(4, PuV), true_case, done)); 173 | il.MarkLabel(true_case); 174 | il.AddInstruction(il.SetRegister( 175 | 4, RdV, il.Xor(4, il.Register(4, RsV), il.Register(4, RtV)))); 176 | il.MarkLabel(done); 177 | } 178 | } 179 | ``` 180 | 181 | * **IL utils**: this module implements BN's 182 | [GetInstructionLowLevelIL](https://api.binary.ninja/binaryninja.architecture-module.html?highlight=text#binaryninja.architecture.Architecture.get_instruction_low_level_il) 183 | API by calling the generated instruction lifters. It lifts all instructions 184 | in a packet, and models the packet's branch semantics. 185 | 186 | * **Packet Context**: is an auxiliary object that tracks all clobbered 187 | registers in a packet. This is used by IL utils module. 188 | 189 | * **Plugin**: program's entry point, it implements and registers the new 190 | 'Hexagon' 191 | [architecture module](https://api.binary.ninja/binaryninja.architecture-module.html). 192 | Architecture module stores decoded instructions in `packet_db`, calls out to 193 | `insn_util` to disassemble instructions, and `il_util` to lift packets. 194 | 195 | ## References 196 | 197 | * [QEMU's Hexagon target](https://github.com/quic/qemu) by Taylor Simpson from 198 | Qualcomm Innovation Center. 199 | 200 | * Qualcomm Hexagon V67 Programmer’s Reference Manual, 80-N2040-45 Rev. B, 201 | February 25, 2020. Can be downloaded from 202 | [Hexagon SDK](https://developer.qualcomm.com/software/hexagon-dsp-sdk/tools) 203 | website. 204 | 205 | * Binary Ninja [API](https://github.com/Vector35/binaryninja-api) and 206 | [documentation](https://api.binary.ninja/). 207 | 208 | * Official BN architecture plugins: 209 | [arch-x86](https://github.com/Vector35/arch-x86), 210 | [arch-arm64](https://github.com/Vector35/arch-arm64), 211 | [arch-mips](https://github.com/Vector35/arch-mips). 212 | -------------------------------------------------------------------------------- /docs/images/components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/binja-hexagon/28049a80b7e3e1aba142466cf0dbeb5ba7c396a8/docs/images/components.png -------------------------------------------------------------------------------- /docs/images/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/binja-hexagon/28049a80b7e3e1aba142466cf0dbeb5ba7c396a8/docs/images/screenshot1.png -------------------------------------------------------------------------------- /docs/images/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/binja-hexagon/28049a80b7e3e1aba142466cf0dbeb5ba7c396a8/docs/images/screenshot2.png -------------------------------------------------------------------------------- /docs/setup.md: -------------------------------------------------------------------------------- 1 | ## Setup 2 | 3 | ### Third party dependencies 4 | 5 | Install Python's build dependencies using `pip3`: 6 | 7 | ``` 8 | $ pip3 install -r requirements.txt 9 | ``` 10 | 11 | It is recommended to do so in a separate `venv` environment. One time 12 | initialization: 13 | 14 | ``` 15 | $ python3 -m venv venv 16 | ``` 17 | 18 | Then activate the environment by sourcing its `bin/activate` file: 19 | 20 | ``` 21 | $ source venv/bin/activate 22 | ``` 23 | 24 | Install Binary Ninja Python API: 25 | 26 | ``` 27 | $ python3 ${HOME}/binaryninja/scripts/install_api.py 28 | ``` 29 | 30 | --- 31 | 32 | Download plugin's third party repositories: 33 | 34 | ``` 35 | $ git submodule update --init 36 | ``` 37 | 38 | ### Build 39 | 40 | Build the plugin using `cmake`: 41 | 42 | ``` 43 | $ mkdir build 44 | $ cd build 45 | $ cmake .. 46 | $ make -j 47 | ``` 48 | 49 | The build process accepts the following variables, set using `cmake -D` command 50 | line argument: 51 | 52 | - **BN_INSTALL_DIR**: Binary Ninja installation directory. This parameter is 53 | required in order to find BN's core library. If not specified, cmakes tries 54 | to find BN at its default install location. 55 | 56 | - **USE_DOCKER_BUILD**: Tells build system to cross-compile Hexagon targets in 57 | a custom Docker image. Image is downloaded from QEMU's registry. 58 | 59 | To build using `clang` override CC environment variable and include 60 | `clang_overrides.cmake` as follows: 61 | 62 | ``` 63 | $ CC="$(which clang)" CXX="$(which clang++)" cmake .. \ 64 | -DCMAKE_USER_MAKE_RULES_OVERRIDE="${PWD}/../cmake/clang_overrides.cmake" 65 | ``` 66 | 67 | --- 68 | 69 | `make check` runs all unit tests. Note, a BN professional license is required in 70 | order to run the headless e2e tests. 71 | 72 | ### Binary Ninja plugin 73 | 74 | Add a symlink to the plugin binary: 75 | 76 | ``` 77 | $ ln -s ${PWD}/plugin/libarch_hexagon.so ${HOME}/.binaryninja/plugins/libarch_hexagon.so 78 | ``` 79 | -------------------------------------------------------------------------------- /plugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Google LLC 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along 14 | # with this program; if not, write to the Free Software Foundation, Inc., 15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | # 17 | 18 | # Generate insn text funcs. 19 | set(INSN_TEXT_FUNCS_CC ${CMAKE_CURRENT_BINARY_DIR}/insn_text_funcs_generated.cc) 20 | add_custom_command( 21 | OUTPUT ${INSN_TEXT_FUNCS_CC} 22 | COMMAND PYTHONPATH=${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon ${CMAKE_CURRENT_SOURCE_DIR}/gen_insn_text_funcs.py ${SEMANTICS} ${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon/attribs_def.h ${INSN_TEXT_FUNCS_CC} 23 | COMMAND clang-format -i ${INSN_TEXT_FUNCS_CC} || (exit 0) 24 | DEPENDS gen_insn_text_funcs.py ${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon/hex_common.py ${SEMANTICS} ${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon/attribs_def.h 25 | ) 26 | 27 | add_custom_target(gen_insn_text_funcs 28 | DEPENDS ${INSN_TEXT_FUNCS_CC} 29 | ) 30 | 31 | add_dependencies(gen_insn_text_funcs 32 | hexagon_generated_headers_deps 33 | ) 34 | 35 | add_test(NAME gen_insn_text_funcs_test 36 | COMMAND python3 gen_insn_text_funcs_test.py 37 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 38 | ) 39 | set_tests_properties(gen_insn_text_funcs_test PROPERTIES 40 | ENVIRONMENT PYTHONPATH=${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon 41 | ) 42 | 43 | # Generate il funcs. 44 | set(IL_FUNCS_CC ${CMAKE_CURRENT_BINARY_DIR}/il_funcs_generated.cc) 45 | add_custom_command( 46 | OUTPUT ${IL_FUNCS_CC} 47 | COMMAND PYTHONPATH=${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon ${CMAKE_CURRENT_SOURCE_DIR}/gen_il_funcs.py ${SEMANTICS} ${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon/attribs_def.h ${IL_FUNCS_CC} 48 | COMMAND clang-format -i ${IL_FUNCS_CC} || (exit 0) 49 | DEPENDS gen_il_funcs.py gen_il_funcs_data.py ${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon/hex_common.py ${SEMANTICS} ${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon/attribs_def.h 50 | ) 51 | 52 | add_custom_target(gen_il_funcs 53 | DEPENDS ${IL_FUNCS_CC} 54 | ) 55 | 56 | add_dependencies(gen_il_funcs 57 | hexagon_generated_headers_deps 58 | ) 59 | 60 | add_test(NAME gen_il_funcs_test 61 | COMMAND python3 gen_il_funcs_test.py 62 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 63 | ) 64 | set_tests_properties(gen_il_funcs_test PROPERTIES 65 | ENVIRONMENT PYTHONPATH=${CMAKE_SOURCE_DIR}/third_party/qemu-hexagon 66 | ) 67 | 68 | add_library(plugin_lib 69 | ${INSN_TEXT_FUNCS_CC} 70 | ${IL_FUNCS_CC} 71 | decoder.cc 72 | il_util.cc 73 | insn_util.cc 74 | packet_context.cc 75 | packet_db.cc 76 | text_util.cc 77 | ) 78 | 79 | 80 | target_link_libraries(plugin_lib 81 | binaryninjaapi 82 | interval_map 83 | decoder_c_lib 84 | absl::base 85 | absl::strings 86 | absl::statusor 87 | absl::synchronization 88 | glog 89 | ) 90 | 91 | target_include_directories(plugin_lib 92 | PRIVATE 93 | ${CMAKE_CURRENT_BINARY_DIR} 94 | ) 95 | 96 | function (add_plugin_test name) 97 | add_executable(${name} 98 | ${name}.cc 99 | ) 100 | 101 | target_link_libraries(${name} 102 | plugin_lib 103 | gmock 104 | gtest_main 105 | absl::base 106 | absl::strings 107 | ) 108 | 109 | add_test(${name} ${name}) 110 | add_dependencies(check ${name}) 111 | endfunction() 112 | 113 | add_plugin_test(decoder_test) 114 | add_plugin_test(packet_db_test) 115 | add_plugin_test(il_util_test) 116 | add_plugin_test(insn_util_test) 117 | 118 | add_library(arch_hexagon SHARED 119 | arch_hexagon.cc 120 | ) 121 | 122 | target_link_libraries(arch_hexagon 123 | plugin_lib 124 | binaryninjaapi 125 | ) 126 | 127 | set_target_properties(arch_hexagon PROPERTIES 128 | CXX_STANDARD 17 129 | CXX_VISIBILITY_PRESET hidden 130 | CXX_STANDARD_REQUIRED ON 131 | C_STANDARD 99 132 | C_STANDARD_REQUIRED ON 133 | C_VISIBILITY_PRESET hidden 134 | VISIBILITY_INLINES_HIDDEN ON 135 | POSITION_INDEPENDENT_CODE ON 136 | ) 137 | -------------------------------------------------------------------------------- /plugin/decoder.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #include "plugin/decoder.h" 18 | 19 | #include "absl/status/status.h" 20 | #include "absl/strings/str_cat.h" 21 | #include "third_party/qemu-hexagon/decode.h" 22 | #include "third_party/qemu-hexagon/opcodes.h" 23 | 24 | Decoder::Decoder() { 25 | // Initialize decoding tables. 26 | decode_init(); 27 | opcode_init(); 28 | } 29 | Decoder::~Decoder() {} 30 | 31 | Decoder &Decoder::Get() { 32 | // Return singleton object. 33 | static Decoder *global_decoder = new Decoder(); 34 | return *global_decoder; 35 | } 36 | 37 | absl::StatusOr Decoder::DecodePacket(absl::Span words) { 38 | Packet pkt; 39 | int res = decode_packet_safe(words.size(), words.data(), &pkt, true); 40 | if (res < 0) { 41 | return absl::InternalError(absl::StrFormat("Failed to decode, res = %x", res)); 42 | } 43 | if (res == 0) { 44 | return absl::FailedPreconditionError("Insufficient words in packet"); 45 | } 46 | return pkt; 47 | } 48 | 49 | bool operator==(const Insn &lhs, const Insn &rhs) { 50 | bool ok = (memcmp(lhs.regno, rhs.regno, sizeof(lhs.regno)) == 0); 51 | ok &= (lhs.opcode == rhs.opcode && lhs.iclass == rhs.iclass && 52 | lhs.slot == rhs.slot && lhs.part1 == rhs.part1 && 53 | lhs.extension_valid == rhs.extension_valid && 54 | lhs.which_extended == rhs.which_extended && 55 | lhs.is_endloop == rhs.is_endloop && 56 | lhs.new_value_producer_slot == rhs.new_value_producer_slot && 57 | lhs.hvx_resource == rhs.hvx_resource); 58 | ok &= (memcmp(lhs.immed, rhs.immed, sizeof(lhs.immed)) == 0); 59 | return ok; 60 | } 61 | 62 | bool operator!=(const Insn &lhs, const Insn &rhs) { return !(lhs == rhs); } 63 | 64 | bool operator==(const Packet &lhs, const Packet &rhs) { 65 | bool ok = (lhs.num_insns == rhs.num_insns && 66 | lhs.encod_pkt_size_in_bytes == rhs.encod_pkt_size_in_bytes && 67 | lhs.pkt_has_cof == rhs.pkt_has_cof && 68 | lhs.pkt_has_endloop == rhs.pkt_has_endloop && 69 | lhs.pkt_has_dczeroa == rhs.pkt_has_dczeroa && 70 | lhs.pkt_has_store_s0 == rhs.pkt_has_store_s0 && 71 | lhs.pkt_has_store_s1 == rhs.pkt_has_store_s1 && 72 | lhs.pkt_has_hvx == rhs.pkt_has_hvx && 73 | lhs.pkt_has_extension == rhs.pkt_has_extension); 74 | if (ok) { 75 | for (int i = 0; i < lhs.num_insns; i++) { 76 | ok &= (lhs.insn[i] == rhs.insn[i]); 77 | } 78 | } 79 | return ok; 80 | } 81 | 82 | bool operator!=(const Packet &lhs, const Packet &rhs) { return !(lhs == rhs); } 83 | -------------------------------------------------------------------------------- /plugin/decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "absl/status/statusor.h" 22 | #include "absl/types/span.h" 23 | #include "third_party/qemu-hexagon/attribs.h" 24 | #include "third_party/qemu-hexagon/iclass.h" 25 | #include "third_party/qemu-hexagon/insn.h" 26 | #include "third_party/qemu-hexagon/opcodes.h" 27 | #include "third_party/qemu-hexagon/reg_fields.h" 28 | 29 | class Decoder { 30 | public: 31 | ~Decoder(); 32 | static Decoder &Get(); 33 | 34 | absl::StatusOr DecodePacket(absl::Span words); 35 | 36 | private: 37 | Decoder(); 38 | }; 39 | 40 | bool operator==(const Insn &lhs, const Insn &rhs); 41 | bool operator!=(const Insn &lhs, const Insn &rhs); 42 | bool operator==(const Packet &lhs, const Packet &rhs); 43 | bool operator!=(const Packet &lhs, const Packet &rhs); 44 | -------------------------------------------------------------------------------- /plugin/decoder_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #include "plugin/decoder.h" 18 | 19 | #include "plugin/status_matchers.h" 20 | #include "gtest/gtest.h" 21 | 22 | namespace { 23 | 24 | TEST(DecoderTest, DecodesSingleAluInstruction) { 25 | // 00 e0 00 78 7800e000 { r0 = #256 } 26 | // alu.idef: 27 | // Q6INSN(A2_tfrsi,"Rd32=#s16",ATTRIBS(), 28 | //"transfer signed immediate to register",{ fIMMEXT(siV); RdV=siV;}) 29 | std::vector words = {0x7800e000}; 30 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 31 | EXPECT_EQ(pkt.num_insns, 1); 32 | EXPECT_EQ(pkt.encod_pkt_size_in_bytes, 4); 33 | EXPECT_EQ(pkt.insn[0].opcode, A2_tfrsi); 34 | EXPECT_EQ(pkt.insn[0].iclass, ICLASS_ALU32_2op); 35 | EXPECT_EQ(pkt.insn[0].slot, 3); 36 | EXPECT_EQ(pkt.insn[0].regno[0], 0); 37 | EXPECT_EQ(pkt.insn[0].immed[0], 256); 38 | } 39 | 40 | TEST(DecoderTest, DecodesTwoAluSubInstructions) { 41 | // 02 28 01 28 28012802 { r1 = #0; r2 = #0 } 42 | // subinsns.idef: 43 | // Q6INSN(SA1_seti, "Rd16=#u6", ATTRIBS(A_SUBINSN),"Set 44 | // immed", { fIMMEXT(uiV); RdV=uiV;}) 45 | std::vector words = {0x28012802}; 46 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 47 | EXPECT_EQ(pkt.num_insns, 2); 48 | EXPECT_EQ(pkt.encod_pkt_size_in_bytes, 4); 49 | EXPECT_EQ(pkt.insn[0].opcode, SA1_seti); 50 | EXPECT_EQ(pkt.insn[0].iclass, ICLASS_EXTENDER + 16); 51 | EXPECT_EQ(pkt.insn[0].slot, 1); 52 | EXPECT_EQ(pkt.insn[0].regno[0], 1); 53 | EXPECT_EQ(pkt.insn[0].immed[0], 0); 54 | EXPECT_EQ(pkt.insn[1].opcode, SA1_seti); 55 | EXPECT_EQ(pkt.insn[1].iclass, ICLASS_EXTENDER + 16); 56 | EXPECT_EQ(pkt.insn[1].slot, 0); 57 | EXPECT_EQ(pkt.insn[1].regno[0], 2); 58 | EXPECT_EQ(pkt.insn[1].immed[0], 0); 59 | } 60 | 61 | TEST(DecoderTest, DecodesTwoImmExt) { 62 | // 13c: c0 76 ea 0d 0dea76c0 { immext(#3735924736) 63 | // 140: 11 28 b3 28 28b32811 r3 = ##3735924747; r1 = #1 } 64 | std::vector words = {0x0dea76c0, 0x28b32811}; 65 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 66 | EXPECT_EQ(pkt.num_insns, 3); 67 | EXPECT_EQ(pkt.encod_pkt_size_in_bytes, 8); 68 | EXPECT_EQ(pkt.insn[0].opcode, A4_ext); 69 | EXPECT_TRUE(pkt.insn[1].extension_valid); 70 | EXPECT_EQ(pkt.insn[1].which_extended, 0); 71 | EXPECT_EQ(pkt.insn[1].immed[0], static_cast(3735924747)); 72 | EXPECT_EQ(pkt.insn[1].regno[0], 3); 73 | EXPECT_EQ(pkt.insn[2].immed[0], 1); 74 | EXPECT_EQ(pkt.insn[2].regno[0], 1); 75 | } 76 | 77 | TEST(DecoderTest, DecodesCall) { 78 | // 148: 5c ff ff 5b 5bffff5c { call 0x0 } 79 | std::vector words = {0x5bffff5c}; 80 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 81 | EXPECT_EQ(pkt.num_insns, 1); 82 | EXPECT_EQ(pkt.insn[0].opcode, J2_call); 83 | EXPECT_EQ(pkt.insn[0].iclass, ICLASS_J); 84 | EXPECT_EQ(pkt.insn[0].immed[0], static_cast(0 - 0x148)); 85 | } 86 | 87 | TEST(DecoderTest, DecodesDeallocReturn) { 88 | // c: 1e c0 1e 96 961ec01e { dealloc_return } 89 | std::vector words = {0x961ec01e}; 90 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 91 | EXPECT_EQ(pkt.num_insns, 1); 92 | EXPECT_EQ(pkt.insn[0].opcode, L4_return); 93 | EXPECT_EQ(pkt.insn[0].iclass, ICLASS_LD); 94 | } 95 | 96 | TEST(DecoderTest, DecodesMultipleBranches) { 97 | // 154: ff 7f ff 0f 0fff7fff { immext(#4294967232) 98 | // 158: 28 60 03 10 10036028 p0 = cmp.eq(r3,#0); if (p0.new) jump:t 99 | // 0x128 100 | // 15c: f2 ff ff 59 59fffff2 jump 0x138 } 101 | std::vector words = {0x0fff7fff, 0x10036028, 0x59fffff2}; 102 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 103 | EXPECT_EQ(pkt.num_insns, 3); 104 | EXPECT_EQ(pkt.insn[0].opcode, A4_ext); 105 | EXPECT_EQ(pkt.insn[1].opcode, J4_cmpeqi_tp0_jump_t); 106 | EXPECT_EQ(pkt.insn[1].iclass, ICLASS_CJ); 107 | EXPECT_TRUE(pkt.insn[1].extension_valid); 108 | EXPECT_EQ(pkt.insn[1].which_extended, 0); 109 | EXPECT_EQ(pkt.insn[1].immed[0], static_cast(0x128 - 0x154)); 110 | EXPECT_EQ(pkt.insn[2].iclass, ICLASS_J); 111 | EXPECT_EQ(pkt.insn[2].immed[0], static_cast(0x138 - 0x154)); 112 | } 113 | 114 | TEST(DecoderTest, FailsOnShortPacket) { 115 | // 154: ff 7f ff 0f 0fff7fff { immext(#4294967232) 116 | // 158: 28 60 03 10 10036028 p0 = cmp.eq(r3,#0); if (p0.new) jump:t 117 | // 0x128 118 | // 15c: f2 ff ff 59 59fffff2 jump 0x138 } 119 | std::vector words = {0x0fff7fff, 0x10036028}; 120 | EXPECT_THAT(Decoder::Get().DecodePacket(words), 121 | absl::StatusIs(absl::StatusCode::kFailedPrecondition)); 122 | } 123 | 124 | TEST(DecoderTest, DecodesDotnewStoreRegression) { 125 | // 872c: 02 40 00 78 78004002 { r2 = #0 126 | // 8730: a7 43 00 00 000043a7 immext(#59840) 127 | // 8734: 30 c2 a0 48 48a0c230 memb(##59888) = r2.new } 128 | std::vector words = {0x78004002, 0x000043a7, 0x48a0c230}; 129 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 130 | EXPECT_EQ(pkt.num_insns, 3); 131 | EXPECT_EQ(pkt.insn[0].opcode, A2_tfrsi); 132 | EXPECT_EQ(pkt.insn[1].opcode, A4_ext); 133 | EXPECT_EQ(pkt.insn[2].immed[0], static_cast(59888)); 134 | EXPECT_EQ(pkt.insn[2].opcode, S2_storerbnewgp); 135 | } 136 | 137 | TEST(DecoderTest, FailsSafeOnInvalidCode) { 138 | std::vector words = {0x00006000, 0x0000007f, 0x00000004}; 139 | EXPECT_THAT(Decoder::Get().DecodePacket(words), 140 | absl::StatusIs(absl::StatusCode::kInternal)); 141 | } 142 | 143 | TEST(DecoderTest, DecodesAddsEndLoopInsn) { 144 | // 1c8: 22 80 02 b0 b0028022 { r2 = add(r2,#1) 145 | // 1cc: 00 c0 00 7f 7f00c000 nop } :endloop0 146 | std::vector words = {0xb0028022, 0x7f00c000}; 147 | ASSERT_OK_AND_ASSIGN(Packet pkt, Decoder::Get().DecodePacket(words)); 148 | EXPECT_EQ(pkt.num_insns, 3); 149 | EXPECT_EQ(pkt.insn[0].opcode, A2_addi); 150 | EXPECT_EQ(pkt.insn[1].opcode, A2_nop); 151 | EXPECT_EQ(pkt.insn[2].opcode, J2_endloop0); 152 | } 153 | 154 | TEST(DecoderTest, FailsSafeOnInvalidAsciiStringRegression1) { 155 | // ASCII string: "_CLK failed". 156 | std::vector words = {0x4b4c435f, 0x69616620, 0x2164656c, 0}; 157 | EXPECT_THAT(Decoder::Get().DecodePacket(words), 158 | absl::StatusIs(absl::StatusCode::kInternal)); 159 | } 160 | 161 | TEST(DecoderTest, FailsSafeOnInvalidAsciiStringRegression2) { 162 | // ASCII string: "ub-ID:%d". 163 | // Second word has end-of-packet marker and duplex instructions. 164 | // However, the second sub-instruction fails to decode. 165 | std::vector words = {0x492D6275, 0x64253A44}; 166 | EXPECT_THAT(Decoder::Get().DecodePacket(words), 167 | absl::StatusIs(absl::StatusCode::kInternal)); 168 | } 169 | 170 | } // namespace 171 | -------------------------------------------------------------------------------- /plugin/hex_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | enum { 22 | // 23 | // General registers. 24 | // 25 | HEX_REG_R00 = 0, 26 | HEX_REG_R01 = 1, 27 | HEX_REG_R02 = 2, 28 | HEX_REG_R03 = 3, 29 | HEX_REG_R04 = 4, 30 | HEX_REG_R05 = 5, 31 | HEX_REG_R06 = 6, 32 | HEX_REG_R07 = 7, 33 | HEX_REG_R08 = 8, 34 | HEX_REG_R09 = 9, 35 | HEX_REG_R10 = 10, 36 | HEX_REG_R11 = 11, 37 | HEX_REG_R12 = 12, 38 | HEX_REG_R13 = 13, 39 | HEX_REG_R14 = 14, 40 | HEX_REG_R15 = 15, 41 | HEX_REG_R16 = 16, 42 | HEX_REG_R17 = 17, 43 | HEX_REG_R18 = 18, 44 | HEX_REG_R19 = 19, 45 | HEX_REG_R20 = 20, 46 | HEX_REG_R21 = 21, 47 | HEX_REG_R22 = 22, 48 | HEX_REG_R23 = 23, 49 | HEX_REG_R24 = 24, 50 | HEX_REG_R25 = 25, 51 | HEX_REG_R26 = 26, 52 | HEX_REG_R27 = 27, 53 | HEX_REG_R28 = 28, 54 | HEX_REG_R29 = 29, 55 | HEX_REG_R30 = 30, 56 | HEX_REG_R31 = 31, 57 | 58 | // 59 | // General register aliases. 60 | // 61 | // Stack pointer. 62 | HEX_REG_SP = HEX_REG_R29, 63 | // Frame pointer. 64 | HEX_REG_FP = HEX_REG_R30, 65 | // Link register. 66 | HEX_REG_LR = HEX_REG_R31, 67 | 68 | // 69 | // Control registers. 70 | // 71 | HEX_REG_C00 = 32, 72 | HEX_REG_C01 = 33, 73 | HEX_REG_C02 = 34, 74 | HEX_REG_C03 = 35, 75 | HEX_REG_C04 = 36, 76 | HEX_REG_C05 = 37, 77 | HEX_REG_C06 = 38, 78 | HEX_REG_C07 = 39, 79 | HEX_REG_C08 = 40, 80 | HEX_REG_C09 = 41, 81 | HEX_REG_C10 = 42, 82 | HEX_REG_C11 = 43, 83 | HEX_REG_C12 = 44, 84 | HEX_REG_C13 = 45, 85 | HEX_REG_C14 = 46, 86 | HEX_REG_C15 = 47, 87 | HEX_REG_C16 = 48, 88 | HEX_REG_C17 = 49, 89 | HEX_REG_C18 = 50, 90 | HEX_REG_C19 = 51, 91 | HEX_REG_C20 = 52, 92 | HEX_REG_C21 = 53, 93 | HEX_REG_C22 = 54, 94 | HEX_REG_C23 = 55, 95 | HEX_REG_C24 = 56, 96 | HEX_REG_C25 = 57, 97 | HEX_REG_C26 = 58, 98 | HEX_REG_C27 = 59, 99 | HEX_REG_C28 = 60, 100 | HEX_REG_C29 = 61, 101 | HEX_REG_C30 = 62, 102 | HEX_REG_C31 = 63, 103 | 104 | // 105 | // Aliased control registers 106 | // 107 | // Loop registers. 108 | HEX_REG_SA0 = HEX_REG_C00, 109 | HEX_REG_LC0 = HEX_REG_C01, 110 | HEX_REG_SA1 = HEX_REG_C02, 111 | HEX_REG_LC1 = HEX_REG_C03, 112 | // Predicate registers 3:0 113 | HEX_REG_P3_0 = HEX_REG_C04, 114 | // Modifier registers. 115 | HEX_REG_M0 = HEX_REG_C06, 116 | HEX_REG_M1 = HEX_REG_C07, 117 | // User status register. 118 | HEX_REG_USR = HEX_REG_C08, 119 | // Program counter. 120 | HEX_REG_PC = HEX_REG_C09, 121 | // User general pointer. 122 | HEX_REG_UGP = HEX_REG_C10, 123 | // Global pointer. 124 | HEX_REG_GP = HEX_REG_C11, 125 | // Circular start registers. 126 | HEX_REG_CS0 = HEX_REG_C12, 127 | HEX_REG_CS1 = HEX_REG_C13, 128 | 129 | // 130 | // Sub registers. 131 | // 132 | // Predicate registers modeled as sub registers of HEX_REG_P3_0. 133 | HEX_REG_P0 = 90, 134 | HEX_REG_P1 = 91, 135 | HEX_REG_P2 = 92, 136 | HEX_REG_P3 = 93, 137 | // HW loop configuration modeled as sub register of HEX_REG_USR. 138 | HEX_REG_USR_LPCFG = 94, 139 | 140 | NUM_HEX_REGS = 100, 141 | }; 142 | 143 | // 144 | // System registers 145 | // 146 | enum { 147 | HEX_SREG_SGP0 = 0, 148 | HEX_SREG_SGP1 = 1, 149 | HEX_SREG_STID = 2, 150 | HEX_SREG_ELR = 3, 151 | HEX_SREG_BADVA0 = 4, 152 | HEX_SREG_BADVA1 = 5, 153 | HEX_SREG_SSR = 6, 154 | HEX_SREG_CCR = 7, 155 | HEX_SREG_HTID = 8, 156 | HEX_SREG_BADVA = 9, 157 | HEX_SREG_IMASK = 10, 158 | HEX_SREG_GEVB = 11, 159 | HEX_SREG_EVB = 16, 160 | HEX_SREG_MODECTL = 17, 161 | HEX_SREG_SYSCFG = 18, 162 | HEX_SREG_IPENDAD = 20, 163 | HEX_SREG_VID = 21, 164 | HEX_SREG_VID1 = 22, 165 | HEX_SREG_BESTWAIT = 23, 166 | HEX_SREG_IEL = 24, 167 | HEX_SREG_SCHEDCFG = 25, 168 | HEX_SREG_IAHL = 26, 169 | HEX_SREG_CFGBASE = 27, 170 | HEX_SREG_DIAG = 28, 171 | HEX_SREG_REV = 29, 172 | HEX_SREG_PCYCLELO = 30, 173 | HEX_SREG_PCYCLEHI = 31, 174 | HEX_SREG_ISDBST = 32, 175 | HEX_SREG_ISDBCFG0 = 33, 176 | HEX_SREG_ISDBCFG1 = 34, 177 | HEX_SREG_LIVELOCK = 35, 178 | HEX_SREG_BRKPTPC0 = 36, 179 | HEX_SREG_BRKPTCFG0 = 37, 180 | HEX_SREG_BRKPTPC1 = 38, 181 | HEX_SREG_BRKPTCFG1 = 39, 182 | HEX_SREG_ISDBMBXIN = 40, 183 | HEX_SREG_ISDBMBXOUT = 41, 184 | HEX_SREG_ISDBEN = 42, 185 | HEX_SREG_ISDBGPR = 43, 186 | HEX_SREG_PMUCNT4 = 44, 187 | HEX_SREG_PMUCNT5 = 45, 188 | HEX_SREG_PMUCNT6 = 46, 189 | HEX_SREG_PMUCNT7 = 47, 190 | HEX_SREG_PMUCNT0 = 48, 191 | HEX_SREG_PMUCNT1 = 49, 192 | HEX_SREG_PMUCNT2 = 50, 193 | HEX_SREG_PMUCNT3 = 51, 194 | HEX_SREG_PMUEVTCFG = 52, 195 | HEX_SREG_PMUSTID0 = 53, 196 | HEX_SREG_PMUEVTCFG1 = 54, 197 | HEX_SREG_PMUSTID1 = 55, 198 | HEX_SREG_TIMERLO = 56, 199 | HEX_SREG_TIMERHI = 57, 200 | HEX_SREG_PMUCFG = 58, 201 | HEX_SREG_S59 = 59, 202 | HEX_SREG_S60 = 60, 203 | HEX_SREG_S61 = 61, 204 | HEX_SREG_S62 = 62, 205 | HEX_SREG_S63 = 63, 206 | HEX_SREG_COMMIT1T = 64, 207 | HEX_SREG_COMMIT2T = 65, 208 | HEX_SREG_COMMIT3T = 66, 209 | HEX_SREG_COMMIT4T = 67, 210 | HEX_SREG_COMMIT5T = 68, 211 | HEX_SREG_COMMIT6T = 69, 212 | HEX_SREG_PCYCLE1T = 70, 213 | HEX_SREG_PCYCLE2T = 71, 214 | HEX_SREG_PCYCLE3T = 72, 215 | HEX_SREG_PCYCLE4T = 73, 216 | HEX_SREG_PCYCLE5T = 74, 217 | HEX_SREG_PCYCLE6T = 75, 218 | HEX_SREG_STFINST = 76, 219 | HEX_SREG_ISDBCMD = 77, 220 | HEX_SREG_ISDBVER = 78, 221 | HEX_SREG_BRKPTINFO = 79, 222 | HEX_SREG_RGDR3 = 80, 223 | HEX_SREG_COMMIT7T = 81, 224 | HEX_SREG_COMMIT8T = 82, 225 | HEX_SREG_PCYCLE7T = 83, 226 | HEX_SREG_PCYCLE8T = 84, 227 | HEX_SREG_S85 = 85, 228 | 229 | // Alias system registers 230 | 231 | HEX_SREG_GLB_START = HEX_SREG_EVB 232 | }; 233 | -------------------------------------------------------------------------------- /plugin/il_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "absl/status/status.h" 22 | #include "binaryninjaapi.h" 23 | #include "plugin/decoder.h" 24 | #include "plugin/packet_db.h" 25 | 26 | // Prepares packet for il lifting by removing no-op extender instructions, 27 | // moving dotnew instructions to the end and splitting cmpjump instructions. 28 | // Exported for testing. 29 | Packet PreparePacketForLifting(const Packet &src); 30 | 31 | absl::Status FillBnInstructionLowLevelIL(BinaryNinja::Architecture *arch, 32 | const PacketDb::InsnInfo &input, 33 | size_t &len, 34 | BinaryNinja::LowLevelILFunction &il); 35 | -------------------------------------------------------------------------------- /plugin/il_util_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #include "plugin/il_util.h" 18 | 19 | #include "absl/status/status.h" 20 | #include "plugin/status_matchers.h" 21 | #include "gtest/gtest.h" 22 | 23 | namespace { 24 | 25 | using absl::IsOk; 26 | using absl::MakeSpan; 27 | using testing::Eq; 28 | using testing::Not; 29 | 30 | TEST(IlUtilTest, RemovesImmExtender) { 31 | // 13c: c0 76 ea 0d 0dea76c0 { immext(#3735924736) 32 | // 140: 11 28 b3 28 28b32811 r3 = ##3735924747; r1 = #1 } 33 | std::vector words = {0x0dea76c0, 0x28b32811}; 34 | ASSERT_OK_AND_ASSIGN(Packet src, Decoder::Get().DecodePacket(words)); 35 | EXPECT_EQ(src.num_insns, 3); 36 | EXPECT_EQ(src.insn[0].opcode, A4_ext); 37 | Packet pkt = PreparePacketForLifting(src); 38 | EXPECT_EQ(pkt.num_insns, 2); 39 | EXPECT_NE(pkt.insn[0].opcode, A4_ext); 40 | EXPECT_NE(pkt.insn[1].opcode, A4_ext); 41 | } 42 | 43 | TEST(IlUtilTest, MovesStoresToEnd) { 44 | // TODO: Update this test. 45 | } 46 | 47 | TEST(IlUtilTest, MovesComparesToBeginning) { 48 | // 5c: 04 40 00 00 00004004 { immext(#256) 49 | // 60: 70 58 00 5c 5c005870 if (p0.new) jump:t 0x194 50 | // 64: a4 40 00 58 580040a4 jump 0x1a4 51 | // 68: a0 fb 23 75 7523fba0 p0 = cmp.eq(r3,#-35) } 52 | std::vector words = {0x00004004, 0x5c005870, 0x580040a4, 53 | 0x7523fba0}; 54 | ASSERT_OK_AND_ASSIGN(Packet src, Decoder::Get().DecodePacket(words)); 55 | EXPECT_EQ(src.num_insns, 4); 56 | EXPECT_EQ(src.insn[0].opcode, A4_ext); 57 | EXPECT_EQ(src.insn[1].opcode, J2_jumptnewpt); 58 | EXPECT_EQ(src.insn[2].opcode, J2_jump); 59 | EXPECT_EQ(src.insn[3].opcode, C2_cmpeqi); 60 | Packet pkt = PreparePacketForLifting(src); 61 | EXPECT_EQ(pkt.num_insns, 3); 62 | EXPECT_EQ(pkt.insn[0].opcode, C2_cmpeqi); 63 | EXPECT_EQ(pkt.insn[1].opcode, J2_jumptnewpt); 64 | EXPECT_EQ(pkt.insn[2].opcode, J2_jump); 65 | } 66 | 67 | TEST(IlUtilTest, SplitsCmpJump) { 68 | // 15c: ff 7f ff 0f 0fff7fff { immext(#4294967232) 69 | // 160: 18 6a 02 10 10026a18 p0 = cmp.eq(r2,#10); if (p0.new) jump:t 70 | // 164: ee ff ff 59 59ffffee jump 0x138 } 71 | std::vector words = {0x0fff7fff, 0x10026a18, 0x59ffffee}; 72 | ASSERT_OK_AND_ASSIGN(Packet src, Decoder::Get().DecodePacket(words)); 73 | EXPECT_EQ(src.num_insns, 3); 74 | EXPECT_EQ(src.insn[0].opcode, A4_ext); 75 | EXPECT_EQ(src.insn[1].opcode, J4_cmpeqi_tp0_jump_t); 76 | EXPECT_EQ(src.insn[2].opcode, J2_jump); 77 | Packet pkt = PreparePacketForLifting(src); 78 | EXPECT_EQ(pkt.num_insns, 3); 79 | EXPECT_EQ(pkt.insn[0].opcode, J4_cmpeqi_tp0_jump_t); 80 | EXPECT_TRUE(pkt.insn[0].part1); 81 | EXPECT_EQ(pkt.insn[1].opcode, J4_cmpeqi_tp0_jump_t); 82 | EXPECT_FALSE(pkt.insn[1].part1); 83 | EXPECT_EQ(pkt.insn[2].opcode, J2_jump); 84 | } 85 | 86 | TEST(IlUtilTest, KeepsDualJumpOrder) { 87 | // 000000b4 0650005c { if (P0) jump:t data_c0 {data_c4} 88 | // 000000b8 08400058 jump data_c4 89 | // 000000bc 01c101f3 R1 = add(R1,R1) } 90 | std::vector words = {0x5c005006, 0x58004008, 0xf301c101}; 91 | ASSERT_OK_AND_ASSIGN(Packet src, Decoder::Get().DecodePacket(words)); 92 | EXPECT_EQ(src.num_insns, 3); 93 | EXPECT_EQ(src.insn[0].opcode, J2_jumptpt); 94 | EXPECT_EQ(src.insn[1].opcode, J2_jump); 95 | EXPECT_EQ(src.insn[2].opcode, A2_add); 96 | Packet pkt = PreparePacketForLifting(src); 97 | EXPECT_EQ(pkt.num_insns, 3); 98 | EXPECT_EQ(pkt.insn[0].opcode, J2_jumptpt); 99 | EXPECT_EQ(pkt.insn[1].opcode, J2_jump); 100 | EXPECT_EQ(pkt.insn[2].opcode, A2_add); 101 | } 102 | 103 | } // namespace 104 | -------------------------------------------------------------------------------- /plugin/insn_util.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #include "plugin/insn_util.h" 18 | 19 | #include "absl/status/status.h" 20 | #include "absl/strings/str_cat.h" 21 | #include "glog/logging.h" 22 | #include "plugin/status_macros.h" 23 | 24 | // Defined in insn_text_funcs_generated.cc. 25 | typedef void (*InsnTextFunc)( 26 | uint64_t pc, const Packet &pkt, const Insn &insn, 27 | std::vector &result); 28 | 29 | extern const InsnTextFunc opcode_textptr[XX_LAST_OPCODE]; 30 | 31 | namespace { 32 | 33 | using namespace BinaryNinja; 34 | using absl::Hex; 35 | using absl::StrCat; 36 | 37 | int GetLastInsn(const Packet &pkt) { 38 | int last_insn = pkt.num_insns - 1; 39 | if (pkt.insn[last_insn].is_endloop) { 40 | last_insn--; 41 | } 42 | return last_insn; 43 | } 44 | 45 | absl::Status 46 | FillBnInstructionTextTokensImpl(uint64_t pc, const Packet &pkt, 47 | const Insn &insn, 48 | std::vector &result) { 49 | if (opcode_textptr[insn.opcode] == nullptr) { 50 | return absl::InvalidArgumentError( 51 | StrCat("Unsupported opcode ", insn.opcode)); 52 | } 53 | opcode_textptr[insn.opcode](pc, pkt, insn, result); 54 | return absl::OkStatus(); 55 | } 56 | 57 | } // namespace 58 | 59 | bool IsSubInsn(const Insn &insn) { return GET_ATTRIB(insn.opcode, A_SUBINSN); } 60 | bool IsJump(const Insn &insn) { 61 | return GET_ATTRIB(insn.opcode, A_JUMP) && insn.opcode != J4_hintjumpr; 62 | } 63 | bool IsCall(const Insn &insn) { return GET_ATTRIB(insn.opcode, A_CALL); } 64 | bool IsIndirect(const Insn &insn) { 65 | return GET_ATTRIB(insn.opcode, A_INDIRECT) && insn.opcode != J4_hintjumpr; 66 | } 67 | bool IsCondJump(const Insn &insn) { 68 | return GET_ATTRIB(insn.opcode, A_BN_COND_J); 69 | } 70 | bool IsReturn(const Insn &insn) { return GET_ATTRIB(insn.opcode, A_BN_RETURN); } 71 | bool IsSystem(const Insn &insn) { return GET_ATTRIB(insn.opcode, A_BN_SYSTEM); } 72 | 73 | absl::Status FillBnInstructionInfo(const PacketDb::InsnInfo &input, 74 | BinaryNinja::InstructionInfo &result) { 75 | if (input.insn_addr & 3) { 76 | return absl::InvalidArgumentError( 77 | StrCat("Got unaligned insn address ", Hex(input.insn_addr))); 78 | } 79 | result.length = 4; 80 | const Packet &pkt = input.pkt; 81 | int last_insn = GetLastInsn(pkt); 82 | if (!((input.insn_num == last_insn) || (IsSubInsn(pkt.insn[input.insn_num]) && 83 | input.insn_num + 1 == last_insn))) { 84 | // Populate Packet's branch information only at the last instruction. 85 | return absl::OkStatus(); 86 | } 87 | bool has_cj = false; 88 | bool has_ucj = false; 89 | for (int i = 0; i < pkt.num_insns; i++) { 90 | const Insn &insn = pkt.insn[i]; 91 | has_cj |= IsJump(insn) && !IsIndirect(insn) && IsCondJump(insn); 92 | has_ucj |= IsJump(insn) && !IsIndirect(insn) && !IsCondJump(insn); 93 | } 94 | 95 | for (int i = 0; i < pkt.num_insns; i++) { 96 | const Insn &insn = pkt.insn[i]; 97 | if (IsReturn(insn)) { 98 | if (IsCondJump(insn)) { 99 | // Skip, and do not annotate conditional returns. 100 | } else { 101 | result.AddBranch(FunctionReturn); 102 | } 103 | } else if (IsSystem(insn)) { 104 | if (IsCondJump(insn)) { 105 | // Skip, and do not annotate conditional, indirect jumps. 106 | } else { 107 | result.AddBranch(SystemCall); 108 | } 109 | } else if (IsJump(insn)) { 110 | if (IsIndirect(insn)) { 111 | if (IsCondJump(insn)) { 112 | // Skip, and do not annotate conditional, indirect jumps. 113 | } else { 114 | result.AddBranch(IndirectBranch); 115 | } 116 | } else if (IsCondJump(insn)) { 117 | result.AddBranch(TrueBranch, input.pc + insn.immed[0]); 118 | if (!has_ucj) { 119 | // Add implicit 'else' case. 120 | result.AddBranch(FalseBranch, input.pc + pkt.encod_pkt_size_in_bytes); 121 | } 122 | } else { 123 | auto type = UnconditionalBranch; 124 | if (has_cj) { 125 | // Add explicity 'else' case. 126 | type = FalseBranch; 127 | } 128 | result.AddBranch(type, input.pc + insn.immed[0]); 129 | } 130 | } else if (IsCall(insn)) { 131 | if (IsIndirect(insn)) { 132 | // Skip, and do not annotate indirect calls. 133 | } else { 134 | result.AddBranch(CallDestination, input.pc + insn.immed[0]); 135 | } 136 | } 137 | } 138 | return absl::OkStatus(); 139 | } 140 | 141 | absl::Status FillBnInstructionTextTokens( 142 | const PacketDb::InsnInfo &input, size_t &len, 143 | std::vector &result) { 144 | if (input.insn_addr & 3) { 145 | return absl::InvalidArgumentError( 146 | StrCat("Got unaligned insn address ", Hex(input.insn_addr))); 147 | } 148 | const Packet &pkt = input.pkt; 149 | uint32_t insn_num = input.insn_num; 150 | const Insn &insn = pkt.insn[insn_num]; 151 | // Sub instructions (2B) are printed as a single instruction. 152 | len = 4; 153 | result.emplace_back(TextToken, (input.insn_num == 0 ? "{ " : " ")); 154 | RETURN_IF_ERROR(FillBnInstructionTextTokensImpl(input.pc, pkt, insn, result)); 155 | if (IsSubInsn(insn)) { 156 | CHECK_LT(++insn_num, pkt.num_insns); 157 | const Insn &next = pkt.insn[insn_num]; 158 | result.emplace_back(TextToken, "; "); 159 | RETURN_IF_ERROR( 160 | FillBnInstructionTextTokensImpl(input.pc, pkt, next, result)); 161 | } 162 | int last_insn = GetLastInsn(pkt); 163 | if (insn_num == last_insn) { 164 | result.emplace_back(TextToken, " }"); 165 | if (pkt.pkt_has_endloop) { 166 | switch (pkt.insn[last_insn + 1].opcode) { 167 | case J2_endloop0: 168 | result.emplace_back(TextToken, " :endloop0"); 169 | break; 170 | case J2_endloop1: 171 | result.emplace_back(TextToken, " :endloop1"); 172 | break; 173 | case J2_endloop01: 174 | result.emplace_back(TextToken, " :endloop01"); 175 | break; 176 | } 177 | } 178 | } else { 179 | result.emplace_back(TextToken, " "); 180 | } 181 | return absl::OkStatus(); 182 | } 183 | -------------------------------------------------------------------------------- /plugin/insn_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | #include 22 | 23 | #include "absl/status/status.h" 24 | #include "binaryninjaapi.h" 25 | #include "plugin/packet_db.h" 26 | 27 | absl::Status FillBnInstructionInfo(const PacketDb::InsnInfo &input, 28 | BinaryNinja::InstructionInfo &result); 29 | 30 | absl::Status FillBnInstructionTextTokens( 31 | const PacketDb::InsnInfo &input, size_t &len, 32 | std::vector &result); 33 | 34 | bool IsSubInsn(const Insn &insn); 35 | bool IsJump(const Insn &insn); 36 | bool IsCall(const Insn &insn); 37 | bool IsIndirect(const Insn &insn); 38 | bool IsCondJump(const Insn &insn); 39 | bool IsReturn(const Insn &insn); 40 | bool IsSystem(const Insn &insn); 41 | -------------------------------------------------------------------------------- /plugin/packet_context.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #include "plugin/packet_context.h" 18 | 19 | #include "absl/memory/memory.h" 20 | #include "plugin/hex_regs.h" 21 | #include "third_party/qemu-hexagon/attribs.h" 22 | #include "third_party/qemu-hexagon/iclass.h" 23 | #include "third_party/qemu-hexagon/insn.h" 24 | #include "third_party/qemu-hexagon/opcodes.h" 25 | 26 | #include "glog/logging.h" 27 | 28 | namespace { 29 | 30 | using namespace BinaryNinja; 31 | 32 | std::unique_ptr MakeTempReg(bool rw, int size, int reg, 33 | LowLevelILFunction &il) { 34 | if (rw) { 35 | return absl::make_unique(size, reg, il); 36 | } else { 37 | return absl::make_unique(size, reg); 38 | } 39 | } 40 | 41 | } // namespace 42 | 43 | int MapRegNum(char regtype, int regno) { 44 | if (regtype == 'R' || regtype == 'N') { 45 | return HEX_REG_R00 + regno; 46 | } 47 | if (regtype == 'C') { 48 | return HEX_REG_C00 + regno; 49 | } 50 | if (regtype == 'P') { 51 | return HEX_REG_P0 + regno; 52 | } 53 | LOG(FATAL) << "Unknown regtype " << static_cast(regtype); 54 | return -1; 55 | } 56 | 57 | void TempReg::CopyToTemp(BinaryNinja::LowLevelILFunction &il) { 58 | ExprId expr; 59 | if (size_ == 1) { 60 | expr = il.SetRegister(1, Reg(), il.Register(1, reg_)); 61 | } else if (size_ == 4) { 62 | expr = il.SetRegister(4, Reg(), il.Register(4, reg_)); 63 | } else { 64 | CHECK_EQ(size_, 8); 65 | expr = il.SetRegister(8, Reg(), il.RegisterSplit(4, reg_ + 1, reg_)); 66 | } 67 | il.AddInstruction(expr); 68 | } 69 | 70 | void TempReg::CopyFromTemp(BinaryNinja::LowLevelILFunction &il) { 71 | ExprId expr; 72 | if (size_ == 1) { 73 | expr = il.SetRegister(1, reg_, il.Register(1, Reg())); 74 | } else if (size_ == 4) { 75 | expr = il.SetRegister(4, reg_, il.Register(4, Reg())); 76 | } else { 77 | CHECK_EQ(size_, 8); 78 | expr = il.SetRegisterSplit(4, reg_ + 1, reg_, il.Register(8, Reg())); 79 | } 80 | il.AddInstruction(expr); 81 | } 82 | 83 | PacketContext::PacketContext(BinaryNinja::LowLevelILFunction &il) : il_(il) {} 84 | 85 | PacketContext::~PacketContext() {} 86 | 87 | int PacketContext::AddDestWriteOnlyRegPair(int reg) { 88 | return AddDestReg(false, 8, reg); 89 | } 90 | 91 | int PacketContext::AddDestReadWriteRegPair(int reg) { 92 | return AddDestReg(true, 8, reg); 93 | } 94 | int PacketContext::AddDestWriteOnlyReg(int reg) { 95 | return AddDestReg(false, 4, reg); 96 | } 97 | int PacketContext::AddDestReadWriteReg(int reg) { 98 | return AddDestReg(true, 4, reg); 99 | } 100 | int PacketContext::AddDestWriteOnlyPredReg(int reg) { 101 | CHECK(reg == HEX_REG_P0 || reg == HEX_REG_P1 || reg == HEX_REG_P2 || 102 | reg == HEX_REG_P3); 103 | return AddDestReg(false, 1, reg); 104 | } 105 | int PacketContext::AddDestReadWritePredReg(int reg) { 106 | CHECK(reg == HEX_REG_P0 || reg == HEX_REG_P1 || reg == HEX_REG_P2 || 107 | reg == HEX_REG_P3); 108 | return AddDestReg(true, 1, reg); 109 | } 110 | 111 | int PacketContext::AddDestReg(bool rw, int size, int reg) { 112 | auto it = regs_.find(reg); 113 | if (it == regs_.end()) { 114 | auto out = regs_.emplace(reg, MakeTempReg(rw, size, reg, il_)); 115 | DCHECK(out.second); 116 | it = out.first; 117 | } else { 118 | // TODO: handle the case where a dest register appears as a single 32b 119 | // register, and a 64b pair. For example, 120 | // 121 | // { if (p0) r0 = #0 122 | // if (p0) r1 = #0 123 | // if (!p0) r1:0 = memd(r3+#0) } 124 | // 125 | if (size != it->second->Size()) { 126 | LOG(WARNING) << "Req to add DestReg " << reg << " of size " << size 127 | << " when it is already registered with size " 128 | << it->second->Size(); 129 | } 130 | } 131 | return it->second->Reg(); 132 | } 133 | 134 | void PacketContext::WriteClobberedRegs() { 135 | for (auto &r : regs_) { 136 | r.second->CopyFromTemp(il_); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /plugin/packet_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | #include 22 | #include 23 | 24 | #include "absl/memory/memory.h" 25 | #include "absl/types/optional.h" 26 | #include "binaryninjaapi.h" 27 | #include "plugin/hex_regs.h" 28 | #include "third_party/qemu-hexagon/insn.h" 29 | 30 | // Holds indirect branch destinations. 31 | #define BRANCHR_DEST_ARRAY LLIL_TEMP(200) 32 | 33 | // Holds conditional branch results. 34 | #define BRANCH_TAKEN_ARRAY LLIL_TEMP(210) 35 | 36 | // Maps insn.regno and regtype ('R', 'P') from insn type 37 | // to HEX_REG enum value: 38 | // MapRegNum('R', 1) -> HEX_REG_R01 39 | // MapRegNum('R', 8) -> HEX_REG_R08 40 | // MapRegNum('P', 0) -> HEX_REG_P0 41 | // MapRegNum('P', 1) -> HEX_REG_P1 42 | int MapRegNum(char regtype, int regno); 43 | 44 | // Temporary source/dest register. 45 | // Maps HEX_REG register to LLIL_TEMP register space: 46 | // HEX_REG_R00 -> LLIL_TEMP(HEX_REG_R00). 47 | class TempReg { 48 | public: 49 | TempReg(int size, int reg, int ss) : size_(size), reg_(reg), subspace_(ss) {} 50 | virtual ~TempReg() = default; 51 | TempReg(const TempReg &) = delete; 52 | TempReg &operator=(const TempReg &) = delete; 53 | 54 | int Size() const { return size_; } 55 | 56 | // Returns the register index in the LLIL_TEMP register space. 57 | int Reg() const { return LLIL_TEMP(subspace_ * NUM_HEX_REGS + reg_); } 58 | 59 | // Adds an IL SetRegister expression that copies the original register 60 | // value to LLIL_TEMP register. 61 | void CopyToTemp(BinaryNinja::LowLevelILFunction &il); 62 | 63 | // Adds an IL SetRegister expression that copies the LLIL_TEMP register 64 | // value to the original register. 65 | void CopyFromTemp(BinaryNinja::LowLevelILFunction &il); 66 | 67 | protected: 68 | const int size_; 69 | const int reg_; 70 | const int subspace_; 71 | }; 72 | 73 | // Register value is copied on construction. 74 | class SourceReg : public TempReg { 75 | public: 76 | SourceReg(int size, int reg, BinaryNinja::LowLevelILFunction &il) 77 | : TempReg(size, reg, /*subspace=*/0) { 78 | CopyToTemp(il); 79 | } 80 | ~SourceReg() override = default; 81 | SourceReg(const SourceReg &) = delete; 82 | SourceReg &operator=(const SourceReg &) = delete; 83 | }; 84 | 85 | // Reads a register pair value on construction. 86 | // Uses a separate LLIL_TEMP subspace to avoid collision with other temporary 87 | // register pairs in the packet. 88 | // See https://github.com/google/binja-hexagon/issues/5 for details. 89 | class SourcePairReg : public TempReg { 90 | public: 91 | SourcePairReg(int reg, BinaryNinja::LowLevelILFunction &il) 92 | : TempReg(/*size=*/8, reg, /*subspace=*/1) { 93 | CopyToTemp(il); 94 | } 95 | ~SourcePairReg() override = default; 96 | SourcePairReg(const SourcePairReg &) = delete; 97 | SourcePairReg &operator=(const SourcePairReg &) = delete; 98 | }; 99 | 100 | class DestWriteOnlyReg : public TempReg { 101 | public: 102 | DestWriteOnlyReg(int size, int reg) : TempReg(size, reg, /*subspace=*/0) {} 103 | ~DestWriteOnlyReg() override = default; 104 | DestWriteOnlyReg(const DestWriteOnlyReg &) = delete; 105 | DestWriteOnlyReg &operator=(const DestWriteOnlyReg &) = delete; 106 | }; 107 | 108 | // Register value is copied on construction. 109 | // LLIL_TEMP register value is copied back to normal register space 110 | // when PacketContext.WriteClobberedRegs() is called. 111 | class DestReadWriteReg : public SourceReg { 112 | public: 113 | DestReadWriteReg(int size, int reg, BinaryNinja::LowLevelILFunction &il) 114 | : SourceReg(size, reg, il) {} 115 | ~DestReadWriteReg() override = default; 116 | DestReadWriteReg(const DestReadWriteReg &) = delete; 117 | DestReadWriteReg &operator=(const DestReadWriteReg &) = delete; 118 | }; 119 | 120 | // Holds all temporary dest registers in the packet. 121 | // Copies all dest registers back to original registers when 122 | // WriteClobberedRegs() is called on packet destruction. 123 | // Managing dest registers in LLIL_TEMP space helps implement the '.new' 124 | // semantics. 125 | class PacketContext { 126 | public: 127 | PacketContext(BinaryNinja::LowLevelILFunction &il); 128 | ~PacketContext(); 129 | PacketContext(const PacketContext &) = delete; 130 | PacketContext &operator=(const PacketContext &) = delete; 131 | 132 | BinaryNinja::LowLevelILFunction &IL() { return il_; } 133 | 134 | // Creates new DestReg and inserts it to |regs_| map if doesn't exist. 135 | // Returns the register index in the LLIL_TEMP register space. 136 | int AddDestWriteOnlyRegPair(int reg); 137 | int AddDestReadWriteRegPair(int reg); 138 | int AddDestWriteOnlyReg(int reg); 139 | int AddDestReadWriteReg(int reg); 140 | int AddDestWriteOnlyPredReg(int reg); 141 | int AddDestReadWritePredReg(int reg); 142 | 143 | // Adds IL instructions that write back all clobbered registers. 144 | void WriteClobberedRegs(); 145 | 146 | private: 147 | int AddDestReg(bool rw, int size, int reg); 148 | 149 | BinaryNinja::LowLevelILFunction &il_; 150 | std::unordered_map> regs_; 151 | }; 152 | -------------------------------------------------------------------------------- /plugin/packet_db.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #include "plugin/packet_db.h" 18 | 19 | #include "absl/types/span.h" 20 | #include "glog/logging.h" 21 | #include "plugin/status_macros.h" 22 | #include "third_party/abseil-cpp/absl/status/status.h" 23 | 24 | bool operator==(const PacketDb::AddressInfo &lhs, 25 | const PacketDb::AddressInfo &rhs) { 26 | return (lhs.start_addr == rhs.start_addr && lhs.pkt == rhs.pkt); 27 | } 28 | 29 | bool operator!=(const PacketDb::AddressInfo &lhs, 30 | const PacketDb::AddressInfo &rhs) { 31 | return !(lhs == rhs); 32 | } 33 | 34 | absl::Status PacketDb::AddBytes(absl::Span data, uint64_t addr) { 35 | if (data.size() < 4 || data.size() % 4 != 0) { 36 | return absl::FailedPreconditionError("Insufficient bytes in data"); 37 | } 38 | auto words = absl::MakeConstSpan( 39 | reinterpret_cast(data.data()), data.size() / 4); 40 | int packets_added = 0; 41 | while (words.size() > 0) { 42 | auto result = Decoder::Get().DecodePacket(words); 43 | if (!result.ok()) { 44 | break; 45 | } 46 | auto pkt = result.value(); 47 | absl::MutexLock lock(&mu_); 48 | map_.SetInterval(addr, addr + pkt.encod_pkt_size_in_bytes, 49 | AddressInfo{addr, pkt}); 50 | addr += pkt.encod_pkt_size_in_bytes; 51 | words = words.subspan(pkt.encod_pkt_size_in_bytes / 4); 52 | packets_added++; 53 | } 54 | if (packets_added == 0) { 55 | return absl::FailedPreconditionError("Insufficient bytes in data"); 56 | } 57 | return absl::OkStatus(); 58 | } 59 | 60 | absl::StatusOr PacketDb::Lookup(uint64_t addr) { 61 | absl::MutexLock lock(&mu_); 62 | const auto &addr_info = map_.find(addr).value(); 63 | if (addr_info.pkt.encod_pkt_size_in_bytes == 0) { 64 | return absl::NotFoundError("Packet not found in interval map"); 65 | } 66 | return FindInstructionInPacket(addr_info, addr); 67 | } 68 | 69 | PacketDb::InsnInfo 70 | PacketDb::FindInstructionInPacket(const PacketDb::AddressInfo &addr_info, 71 | uint64_t addr) { 72 | InsnInfo result = { 73 | .pc = addr_info.start_addr, 74 | .pkt = addr_info.pkt, 75 | .insn_num = 0, 76 | .insn_addr = addr_info.start_addr, 77 | }; 78 | for (; result.insn_num < result.pkt.num_insns; result.insn_num++) { 79 | const Insn &insn = result.pkt.insn[result.insn_num]; 80 | size_t insn_size = (GET_ATTRIB(insn.opcode, A_SUBINSN) ? 2 : 4); 81 | if (result.insn_addr <= addr && addr < result.insn_addr + insn_size) { 82 | break; 83 | } 84 | result.insn_addr += insn_size; 85 | } 86 | return result; 87 | } 88 | -------------------------------------------------------------------------------- /plugin/packet_db.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "absl/status/statusor.h" 22 | #include "absl/synchronization/mutex.h" 23 | #include "absl/types/span.h" 24 | #include "plugin/decoder.h" 25 | #include "third_party/chromium/blink/interval_map.h" 26 | 27 | // Manages an address -> Packet database. 28 | // Access is thread safe. 29 | class PacketDb { 30 | public: 31 | struct AddressInfo { 32 | uint64_t start_addr; 33 | Packet pkt; 34 | }; 35 | 36 | struct InsnInfo { 37 | uint64_t pc; 38 | Packet pkt; 39 | uint32_t insn_num; 40 | uint64_t insn_addr; 41 | }; 42 | 43 | PacketDb() = default; 44 | ~PacketDb() = default; 45 | 46 | // Decodes new input bytes and updates the map. 47 | // Returns Ok if at least one new packet was added. 48 | absl::Status AddBytes(absl::Span data, uint64_t addr) 49 | ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); 50 | 51 | // Looks up a previously decoded instruction at |addr|. 52 | absl::StatusOr Lookup(uint64_t addr) 53 | ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); 54 | 55 | private: 56 | static InsnInfo FindInstructionInPacket(const AddressInfo &addr_info, 57 | uint64_t addr); 58 | 59 | absl::Mutex mu_; 60 | media::IntervalMap map_ ABSL_GUARDED_BY(mu_); 61 | }; 62 | -------------------------------------------------------------------------------- /plugin/relocs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | enum ElfHexagonRelocationType { 22 | R_HEX_NONE = 0, 23 | R_HEX_B22_PCREL = 1, 24 | R_HEX_B15_PCREL = 2, 25 | R_HEX_B7_PCREL = 3, 26 | R_HEX_LO16 = 4, 27 | R_HEX_HI16 = 5, 28 | R_HEX_32 = 6, 29 | R_HEX_16 = 7, 30 | R_HEX_8 = 8, 31 | R_HEX_GPREL16_0 = 9, 32 | R_HEX_GPREL16_1 = 10, 33 | R_HEX_GPREL16_2 = 11, 34 | R_HEX_GPREL16_3 = 12, 35 | R_HEX_HL16 = 13, 36 | R_HEX_B13_PCREL = 14, 37 | R_HEX_B9_PCREL = 15, 38 | R_HEX_B32_PCREL_X = 16, 39 | R_HEX_32_6_X = 17, 40 | R_HEX_B22_PCREL_X = 18, 41 | R_HEX_B15_PCREL_X = 19, 42 | R_HEX_B13_PCREL_X = 20, 43 | R_HEX_B9_PCREL_X = 21, 44 | R_HEX_B7_PCREL_X = 22, 45 | R_HEX_16_X = 23, 46 | R_HEX_12_X = 24, 47 | R_HEX_11_X = 25, 48 | R_HEX_10_X = 26, 49 | R_HEX_9_X = 27, 50 | R_HEX_8_X = 28, 51 | R_HEX_7_X = 29, 52 | R_HEX_6_X = 30, 53 | R_HEX_32_PCREL = 31, 54 | R_HEX_COPY = 32, 55 | R_HEX_GLOB_DAT = 33, 56 | R_HEX_JMP_SLOT = 34, 57 | R_HEX_RELATIVE = 35, 58 | R_HEX_PLT_B22_PCREL = 36, 59 | R_HEX_GOTREL_LO16 = 37, 60 | R_HEX_GOTREL_HI16 = 38, 61 | R_HEX_GOTREL_32 = 39, 62 | R_HEX_GOT_LO16 = 40, 63 | R_HEX_GOT_HI16 = 41, 64 | R_HEX_GOT_32 = 42, 65 | R_HEX_GOT_16 = 43, 66 | R_HEX_DTPMOD_32 = 44, 67 | R_HEX_DTPREL_LO16 = 45, 68 | R_HEX_DTPREL_HI16 = 46, 69 | R_HEX_DTPREL_32 = 47, 70 | R_HEX_DTPREL_16 = 48, 71 | R_HEX_GD_PLT_B22_PCREL = 49, 72 | R_HEX_GD_GOT_LO16 = 50, 73 | R_HEX_GD_GOT_HI16 = 51, 74 | R_HEX_GD_GOT_32 = 52, 75 | R_HEX_GD_GOT_16 = 53, 76 | R_HEX_IE_LO16 = 54, 77 | R_HEX_IE_HI16 = 55, 78 | R_HEX_IE_32 = 56, 79 | R_HEX_IE_GOT_LO16 = 57, 80 | R_HEX_IE_GOT_HI16 = 58, 81 | R_HEX_IE_GOT_32 = 59, 82 | R_HEX_IE_GOT_16 = 60, 83 | R_HEX_TPREL_LO16 = 61, 84 | R_HEX_TPREL_HI16 = 62, 85 | R_HEX_TPREL_32 = 63, 86 | R_HEX_TPREL_16 = 64, 87 | R_HEX_6_PCREL_X = 65, 88 | R_HEX_GOTREL_32_6_X = 66, 89 | R_HEX_GOTREL_16_X = 67, 90 | R_HEX_GOTREL_11_X = 68, 91 | R_HEX_GOT_32_6_X = 69, 92 | R_HEX_GOT_16_X = 70, 93 | R_HEX_GOT_11_X = 71, 94 | R_HEX_DTPREL_32_6_X = 72, 95 | R_HEX_DTPREL_16_X = 73, 96 | R_HEX_DTPREL_11_X = 74, 97 | R_HEX_GD_GOT_32_6_X = 75, 98 | R_HEX_GD_GOT_16_X = 76, 99 | R_HEX_GD_GOT_11_X = 77, 100 | R_HEX_IE_32_6_X = 78, 101 | R_HEX_IE_16_X = 79, 102 | R_HEX_IE_GOT_32_6_X = 80, 103 | R_HEX_IE_GOT_16_X = 81, 104 | R_HEX_IE_GOT_11_X = 82, 105 | R_HEX_TPREL_32_6_X = 83, 106 | R_HEX_TPREL_16_X = 84, 107 | R_HEX_TPREL_11_X = 85, 108 | R_HEX_LD_PLT_B22_PCREL = 86, 109 | R_HEX_LD_GOT_LO16 = 87, 110 | R_HEX_LD_GOT_HI16 = 88, 111 | R_HEX_LD_GOT_32 = 89, 112 | R_HEX_LD_GOT_16 = 90, 113 | R_HEX_LD_GOT_32_6_X = 91, 114 | R_HEX_LD_GOT_16_X = 92, 115 | R_HEX_LD_GOT_11_X = 93, 116 | R_HEX_23_REG = 94, 117 | R_HEX_GD_PLT_B22_PCREL_X = 95, 118 | R_HEX_GD_PLT_B32_PCREL_X = 96, 119 | R_HEX_LD_PLT_B22_PCREL_X = 97, 120 | R_HEX_LD_PLT_B32_PCREL_X = 98, 121 | R_HEX_27_REG = 99, 122 | }; 123 | -------------------------------------------------------------------------------- /plugin/status_macros.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #pragma once 18 | 19 | #include "absl/base/optimization.h" 20 | #include "absl/status/status.h" 21 | 22 | // Internal helper for concatenating macro values. 23 | #define MACROS_IMPL_CONCAT_INNER_(x, y) x##y 24 | #define MACROS_IMPL_CONCAT(x, y) MACROS_IMPL_CONCAT_INNER_(x, y) 25 | 26 | #define RETURN_IF_ERROR(expr) \ 27 | do { \ 28 | const auto status = (expr); \ 29 | if (ABSL_PREDICT_FALSE(!status.ok())) { \ 30 | return status; \ 31 | } \ 32 | } while (0); 33 | 34 | #define ASSIGN_OR_RETURN(lhs, rexpr) \ 35 | ASSIGN_OR_RETURN_IMPL(MACROS_IMPL_CONCAT(_statusor, __LINE__), lhs, rexpr) 36 | 37 | #define ASSIGN_OR_RETURN_IMPL(statusor, lhs, rexpr) \ 38 | auto statusor = (rexpr); \ 39 | if (ABSL_PREDICT_FALSE(!statusor.ok())) { \ 40 | return statusor.status(); \ 41 | } \ 42 | lhs = std::move(statusor).value(); 43 | -------------------------------------------------------------------------------- /plugin/status_matchers.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Google LLC 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License along 14 | // with this program; if not, write to the Free Software Foundation, Inc., 15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "absl/status/status.h" 22 | #include "absl/status/statusor.h" 23 | #include "absl/types/optional.h" 24 | #include "plugin/status_macros.h" 25 | #include "gmock/gmock.h" 26 | 27 | #define ASSERT_OK_AND_ASSIGN(lhs, rexpr) \ 28 | ASSERT_OK_AND_ASSIGN_IMPL(MACROS_IMPL_CONCAT(_statusor, __LINE__), lhs, rexpr) 29 | 30 | #define ASSERT_OK_AND_ASSIGN_IMPL(statusor, lhs, rexpr) \ 31 | auto statusor = (rexpr); \ 32 | ASSERT_THAT(statusor.status(), absl::IsOk()); \ 33 | lhs = std::move(statusor).value(); 34 | 35 | namespace absl { 36 | namespace internal { 37 | 38 | class IsOkMatcher { 39 | public: 40 | template 41 | bool MatchAndExplain(const StatusT &status_container, 42 | ::testing::MatchResultListener *listener) const { 43 | if (!status_container.ok()) { 44 | *listener << "which is not OK"; 45 | return false; 46 | } 47 | return true; 48 | } 49 | 50 | void DescribeTo(std::ostream *os) const { *os << "is OK"; } 51 | 52 | void DescribeNegationTo(std::ostream *os) const { *os << "is not OK"; } 53 | }; 54 | 55 | class StatusIsMatcher { 56 | public: 57 | StatusIsMatcher(const StatusIsMatcher &) = default; 58 | 59 | StatusIsMatcher(absl::StatusCode code, 60 | absl::optional message) 61 | : code_(code), message_(message) {} 62 | 63 | template 64 | bool MatchAndExplain(const T &value, 65 | ::testing::MatchResultListener *listener) const { 66 | auto status = GetStatus(value); 67 | if (code_ != status.code()) { 68 | *listener << "whose error code is " 69 | << absl::StatusCodeToString(status.code()); 70 | return false; 71 | } 72 | if (message_.has_value() && status.message() != message_.value()) { 73 | *listener << "whose error message is '" << message_.value() << "'"; 74 | return false; 75 | } 76 | return true; 77 | } 78 | 79 | void DescribeTo(std::ostream *os) const { 80 | *os << "has a status code that is " << absl::StatusCodeToString(code_); 81 | if (message_.has_value()) { 82 | *os << ", and has an error message that is '" << message_.value() << "'"; 83 | } 84 | } 85 | 86 | void DescribeNegationTo(std::ostream *os) const { 87 | *os << "has a status code that is not " << absl::StatusCodeToString(code_); 88 | if (message_.has_value()) { 89 | *os << ", and has an error message that is not '" << message_.value() 90 | << "'"; 91 | } 92 | } 93 | 94 | private: 95 | template ().code())>::value, 98 | int>::type = 0> 99 | static const StatusT &GetStatus(const StatusT &status) { 100 | return status; 101 | } 102 | 103 | template ().status())> 105 | static StatusT GetStatus(const StatusOrT &status_or) { 106 | return status_or.status(); 107 | } 108 | 109 | const absl::StatusCode code_; 110 | const absl::optional message_; 111 | }; 112 | 113 | } // namespace internal 114 | 115 | inline ::testing::PolymorphicMatcher IsOk() { 116 | return ::testing::MakePolymorphicMatcher(internal::IsOkMatcher{}); 117 | } 118 | 119 | inline ::testing::PolymorphicMatcher 120 | StatusIs(absl::StatusCode code, 121 | absl::optional message = absl::nullopt) { 122 | return ::testing::MakePolymorphicMatcher( 123 | internal::StatusIsMatcher(code, message)); 124 | } 125 | 126 | } // namespace absl 127 | -------------------------------------------------------------------------------- /plugin/text_util.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | #include "plugin/text_util.h" 19 | 20 | #include "absl/strings/str_cat.h" 21 | #include "glog/logging.h" 22 | #include "plugin/hex_regs.h" 23 | 24 | namespace { 25 | 26 | std::string GeneralRegisterName(uint32_t reg) { 27 | switch (reg) { 28 | case HEX_REG_R00 ... HEX_REG_R28: 29 | return absl::StrCat("R", reg - HEX_REG_R00); 30 | case HEX_REG_SP: // R29 31 | return "SP"; 32 | case HEX_REG_FP: // R30 33 | return "FP"; 34 | case HEX_REG_LR: // R31 35 | return "LR"; 36 | default: 37 | LOG(FATAL) << "Unexpected general register reg " << reg; 38 | } 39 | return ""; 40 | } 41 | 42 | std::string ControlRegisterName(uint32_t reg) { 43 | switch (reg) { 44 | case HEX_REG_SA0: // C00 45 | return "SA0"; 46 | case HEX_REG_LC0: // C01 47 | return "LC0"; 48 | case HEX_REG_SA1: // C02 49 | return "SA1"; 50 | case HEX_REG_LC1: // C03 51 | return "LC1"; 52 | case HEX_REG_P3_0: // C04 53 | return "P3:0"; 54 | case HEX_REG_C05: 55 | return "C5"; 56 | case HEX_REG_M0: // C06 57 | return "M0"; 58 | case HEX_REG_M1: // C07 59 | return "M1"; 60 | case HEX_REG_USR: // C08 61 | return "USR"; 62 | case HEX_REG_PC: // C09 63 | return "PC"; 64 | case HEX_REG_UGP: // C10 65 | return "UGP"; 66 | case HEX_REG_GP: // C11 67 | return "GP"; 68 | case HEX_REG_CS0: // C12 69 | return "CS0"; 70 | case HEX_REG_CS1: // C13 71 | return "CS1"; 72 | case HEX_REG_C14 ... HEX_REG_C31: 73 | return absl::StrCat("C", reg - HEX_REG_C00); 74 | default: 75 | LOG(FATAL) << "Unexpected control register reg " << reg; 76 | } 77 | return ""; 78 | } 79 | 80 | std::string PredicateRegisterName(uint32_t reg) { 81 | switch (reg) { 82 | case HEX_REG_P0: 83 | return "P0"; 84 | case HEX_REG_P1: 85 | return "P1"; 86 | case HEX_REG_P2: 87 | return "P2"; 88 | case HEX_REG_P3: 89 | return "P3"; 90 | default: 91 | LOG(FATAL) << "Unexpected predicate register reg " << reg; 92 | } 93 | return ""; 94 | } 95 | 96 | std::string SystemRegisterName(uint32_t reg) { 97 | switch (reg) { 98 | case HEX_SREG_SGP0: 99 | return "SGP0"; 100 | case HEX_SREG_SGP1: 101 | return "SGP1"; 102 | case HEX_SREG_STID: 103 | return "STID"; 104 | case HEX_SREG_ELR: 105 | return "ELR"; 106 | case HEX_SREG_BADVA0: 107 | return "BADVA0"; 108 | case HEX_SREG_BADVA1: 109 | return "BADVA1"; 110 | case HEX_SREG_SSR: 111 | return "SSR"; 112 | case HEX_SREG_CCR: 113 | return "CCR"; 114 | case HEX_SREG_HTID: 115 | return "HTID"; 116 | case HEX_SREG_BADVA: 117 | return "BADVA"; 118 | case HEX_SREG_IMASK: 119 | return "IMASK"; 120 | case HEX_SREG_GEVB: 121 | return "GEVB"; 122 | case HEX_SREG_EVB: 123 | return "EVB"; 124 | case HEX_SREG_MODECTL: 125 | return "MODECTL"; 126 | case HEX_SREG_SYSCFG: 127 | return "SYSCFG"; 128 | case HEX_SREG_IPENDAD: 129 | return "IPENDAD"; 130 | case HEX_SREG_VID: 131 | return "VID"; 132 | case HEX_SREG_VID1: 133 | return "VID1"; 134 | case HEX_SREG_BESTWAIT: 135 | return "BESTWAIT"; 136 | case HEX_SREG_IEL: 137 | return "IEL"; 138 | case HEX_SREG_SCHEDCFG: 139 | return "SCHEDCFG"; 140 | case HEX_SREG_IAHL: 141 | return "IAHL"; 142 | case HEX_SREG_CFGBASE: 143 | return "CFGBASE"; 144 | case HEX_SREG_DIAG: 145 | return "DIAG"; 146 | case HEX_SREG_REV: 147 | return "REV"; 148 | case HEX_SREG_PCYCLELO: 149 | return "PCYCLELO"; 150 | case HEX_SREG_PCYCLEHI: 151 | return "PCYCLEHI"; 152 | case HEX_SREG_ISDBST: 153 | return "ISDBST"; 154 | case HEX_SREG_ISDBCFG0: 155 | return "ISDBCFG0"; 156 | case HEX_SREG_ISDBCFG1: 157 | return "ISDBCFG1"; 158 | case HEX_SREG_LIVELOCK: 159 | return "LIVELOCK"; 160 | case HEX_SREG_BRKPTPC0: 161 | return "BRKPTPC0"; 162 | case HEX_SREG_BRKPTCFG0: 163 | return "BRKPTCFG0"; 164 | case HEX_SREG_BRKPTPC1: 165 | return "BRKPTPC1"; 166 | case HEX_SREG_BRKPTCFG1: 167 | return "BRKPTCFG1"; 168 | case HEX_SREG_ISDBMBXIN: 169 | return "ISDBMBXIN"; 170 | case HEX_SREG_ISDBMBXOUT: 171 | return "ISDBMBXOUT"; 172 | case HEX_SREG_ISDBEN: 173 | return "ISDBEN"; 174 | case HEX_SREG_ISDBGPR: 175 | return "ISDBGPR"; 176 | case HEX_SREG_PMUCNT4: 177 | return "PMUCNT4"; 178 | case HEX_SREG_PMUCNT5: 179 | return "PMUCNT5"; 180 | case HEX_SREG_PMUCNT6: 181 | return "PMUCNT6"; 182 | case HEX_SREG_PMUCNT7: 183 | return "PMUCNT7"; 184 | case HEX_SREG_PMUCNT0: 185 | return "PMUCNT0"; 186 | case HEX_SREG_PMUCNT1: 187 | return "PMUCNT1"; 188 | case HEX_SREG_PMUCNT2: 189 | return "PMUCNT2"; 190 | case HEX_SREG_PMUCNT3: 191 | return "PMUCNT3"; 192 | case HEX_SREG_PMUEVTCFG: 193 | return "PMUEVTCFG"; 194 | case HEX_SREG_PMUSTID0: 195 | return "PMUSTID0"; 196 | case HEX_SREG_PMUEVTCFG1: 197 | return "PMUEVTCFG1"; 198 | case HEX_SREG_PMUSTID1: 199 | return "PMUSTID1"; 200 | case HEX_SREG_TIMERLO: 201 | return "TIMERLO"; 202 | case HEX_SREG_TIMERHI: 203 | return "TIMERHI"; 204 | case HEX_SREG_PMUCFG: 205 | return "PMUCFG"; 206 | case HEX_SREG_S59: 207 | return "S59"; 208 | case HEX_SREG_S60: 209 | return "S60"; 210 | case HEX_SREG_S61: 211 | return "S61"; 212 | case HEX_SREG_S62: 213 | return "S62"; 214 | case HEX_SREG_S63: 215 | return "S63"; 216 | case HEX_SREG_COMMIT1T: 217 | return "COMMIT1T"; 218 | case HEX_SREG_COMMIT2T: 219 | return "COMMIT2T"; 220 | case HEX_SREG_COMMIT3T: 221 | return "COMMIT3T"; 222 | case HEX_SREG_COMMIT4T: 223 | return "COMMIT4T"; 224 | case HEX_SREG_COMMIT5T: 225 | return "COMMIT5T"; 226 | case HEX_SREG_COMMIT6T: 227 | return "COMMIT6T"; 228 | case HEX_SREG_PCYCLE1T: 229 | return "PCYCLE1T"; 230 | case HEX_SREG_PCYCLE2T: 231 | return "PCYCLE2T"; 232 | case HEX_SREG_PCYCLE3T: 233 | return "PCYCLE3T"; 234 | case HEX_SREG_PCYCLE4T: 235 | return "PCYCLE4T"; 236 | case HEX_SREG_PCYCLE5T: 237 | return "PCYCLE5T"; 238 | case HEX_SREG_PCYCLE6T: 239 | return "PCYCLE6T"; 240 | case HEX_SREG_STFINST: 241 | return "STFINST"; 242 | case HEX_SREG_ISDBCMD: 243 | return "ISDBCMD"; 244 | case HEX_SREG_ISDBVER: 245 | return "ISDBVER"; 246 | case HEX_SREG_BRKPTINFO: 247 | return "BRKPTINFO"; 248 | case HEX_SREG_RGDR3: 249 | return "RGDR3"; 250 | case HEX_SREG_COMMIT7T: 251 | return "COMMIT7T"; 252 | case HEX_SREG_COMMIT8T: 253 | return "COMMIT8T"; 254 | case HEX_SREG_PCYCLE7T: 255 | return "PCYCLE7T"; 256 | case HEX_SREG_PCYCLE8T: 257 | return "PCYCLE8T"; 258 | case HEX_SREG_S85: 259 | return "S85"; 260 | default: 261 | LOG(FATAL) << "Unexpected system register reg " << reg; 262 | } 263 | return ""; 264 | } 265 | 266 | } // namespace 267 | 268 | std::string GetRegisterName(absl::string_view reg_type, 269 | absl::string_view hi_low_modifier, int regno) { 270 | std::string out; 271 | if (reg_type == "R" || reg_type == "N") { 272 | out = GeneralRegisterName(HEX_REG_R00 + regno); 273 | } else if (reg_type == "C") { 274 | out = ControlRegisterName(HEX_REG_C00 + regno); 275 | } else if (reg_type == "P") { 276 | out = PredicateRegisterName(HEX_REG_P0 + regno); 277 | } else if (reg_type == "S") { 278 | out = SystemRegisterName(HEX_SREG_SGP0 + regno); 279 | } else { 280 | out = absl::StrCat(reg_type, regno); 281 | } 282 | if (!hi_low_modifier.empty()) { 283 | absl::StrAppend(&out, ".", hi_low_modifier); 284 | } 285 | return out; 286 | } 287 | -------------------------------------------------------------------------------- /plugin/text_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "absl/strings/string_view.h" 22 | 23 | // Instruction text tokenizer helper. 24 | // Returns register name for disassembly listing. 25 | // ('Rt', 10) -> "R10" 26 | // ('Rs', 29) -> "SP" 27 | // ('Rss', 4) -> "R05:R04" 28 | // ('Rd.L', 4) -> "R04.L" 29 | std::string GetRegisterName(absl::string_view reg_type, 30 | absl::string_view hi_low_modifier, int regno); 31 | -------------------------------------------------------------------------------- /plugin/type_util.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2020 Google LLC 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | 18 | import collections 19 | import inspect 20 | import sys 21 | import types 22 | import typing 23 | 24 | 25 | def type_check(func): 26 | '''A decorator for simple type checks at run-time. 27 | So far this only works for simple types, Any, Tuple, Union and Optional. 28 | The return type can be a simple generator. 29 | ''' 30 | if skip_type_check: 31 | return func 32 | type_hints = typing.get_type_hints(func) 33 | func_args = inspect.getfullargspec(func)[0] 34 | 35 | def has_any_type(val, type_list): 36 | return any(has_type(val, t) for t in type_list) 37 | 38 | def has_type(val, type_hint): 39 | if type_hint == typing.Any: 40 | return True 41 | if isinstance(type_hint, typing._GenericAlias): 42 | orig = type_hint.__origin__ 43 | if orig == typing.Union: 44 | return has_any_type(val, type_hint.__args__) 45 | if orig == list: 46 | if not isinstance(val, list): 47 | return False 48 | return all(has_any_type(x, type_hint.__args__) for x in val) 49 | if orig == tuple: 50 | if not isinstance(val, tuple): 51 | return False 52 | if len(val) != len(type_hint.__args__): 53 | return False 54 | return all(has_type(v, t) for v, t in zip(val, type_hint.__args__)) 55 | if isinstance(type_hint, type): 56 | return isinstance(val, type_hint) 57 | else: 58 | # Python 3.9 adds type hints such as list[int]. 59 | # These will be of type typing.GenericAlias 60 | raise TypeError("unknown type:", type_hint) 61 | 62 | def check_type(name, val): 63 | if name in type_hints: 64 | type_hint = type_hints[name] 65 | if not has_type(val, type_hint): 66 | raise TypeError("%s is of type %s expected: %s\nval:%s" % 67 | (name, type(val), type_hint, repr(val))) 68 | 69 | def check_generator(name, val): 70 | '''Gets a generator and returns a type checked generator''' 71 | if name not in type_hints: 72 | yield from val 73 | else: 74 | type_hint = type_hints[name] 75 | if (isinstance(type_hint, typing._GenericAlias) and 76 | type_hint.__origin__ == collections.abc.Generator): 77 | res_type = type_hint.__args__[0] 78 | # SendType and ReturnType are not implemented 79 | assert type_hint.__args__[1] is type(None) 80 | assert type_hint.__args__[2] is type(None) 81 | for y in val: 82 | if has_type(y, res_type): 83 | yield y 84 | else: 85 | raise TypeError( 86 | "iterator element is of type %s expected: %s\nval:%s" % 87 | (type(y), res_type, repr(y))) 88 | else: 89 | raise TypeError("%s is of type %s expected: %s\nval:%s" % 90 | (name, type(val), type_hint, repr(val))) 91 | 92 | def wrapper(*args, **kwargs): 93 | for i, val in enumerate(args): 94 | check_type(func_args[i], val) 95 | for n, val in kwargs.items(): 96 | check_type(n, val) 97 | res = func(*args, **kwargs) 98 | # Allowing generators as return type 99 | if isinstance(res, types.GeneratorType): 100 | return check_generator('return', res) 101 | else: 102 | check_type('return', res) 103 | return res 104 | 105 | if func.__doc__: 106 | wrapper.__doc__ = func.__doc__ 107 | return wrapper 108 | 109 | 110 | skip_type_check = False 111 | if sys.version_info.minor < 7: 112 | skip_type_check = True 113 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | lark-parser==0.11.1 2 | pcpp==1.22 3 | -------------------------------------------------------------------------------- /scripts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Google LLC 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along 14 | # with this program; if not, write to the Free Software Foundation, Inc., 15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | # 17 | configure_file( 18 | ${CMAKE_CURRENT_SOURCE_DIR}/bn_disasm.py.in 19 | bn_disasm.py 20 | ) 21 | 22 | -------------------------------------------------------------------------------- /scripts/bn_disasm.py.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import enum 4 | import sys 5 | import os 6 | sys.path.append(os.path.join('${BN_INSTALL_DIR}', 'python')) 7 | 8 | try: 9 | import binaryninja as binja 10 | except ImportError: 11 | print('Failed to import binaryninja Python API. Check BN_INSTALL_DIR.') 12 | sys.exit(1) 13 | 14 | 15 | class Listing(enum.Enum): 16 | disasm = 'disasm' 17 | llil = 'llil' 18 | mlil = 'mlil' 19 | hlil = 'hlil' 20 | 21 | def __str__(self): 22 | return self.value 23 | 24 | 25 | def main(): 26 | parser = argparse.ArgumentParser() 27 | parser.add_argument( 28 | '--listing', 29 | default=Listing.disasm, 30 | metavar='LISTING', 31 | type=Listing, 32 | choices=list(Listing)) 33 | parser.add_argument( 34 | 'input', metavar='INPUT', type=str, help='Binary file to disasm') 35 | args = parser.parse_args() 36 | 37 | print('Analyzing {0}'.format(args.input)) 38 | binja.log.log_to_stdout(True) 39 | bv = binja.BinaryViewType.get_view_of_file(args.input) 40 | 41 | if args.listing == Listing.disasm: 42 | for line in bv.linear_disassembly: 43 | print(line) 44 | elif args.listing == Listing.llil: 45 | for func in bv.functions: 46 | print('{0}:'.format(func.name)) 47 | for block in func.llil: 48 | for insn in block: 49 | print('\t{0}: {1}'.format(insn.instr_index, insn)) 50 | print('') 51 | elif args.listing == Listing.mlil: 52 | for func in bv.functions: 53 | print('{0}:'.format(func.name)) 54 | for block in func.mlil: 55 | for insn in block: 56 | print('\t{0}: {1}'.format(insn.instr_index, insn)) 57 | print('') 58 | elif args.listing == Listing.hlil: 59 | for func in bv.functions: 60 | print('{0}:'.format(func.name)) 61 | for line in func.hlil.root.lines: 62 | print('\t{0}'.format(line)) 63 | print('') 64 | 65 | 66 | if __name__ == '__main__': 67 | sys.exit(main()) 68 | -------------------------------------------------------------------------------- /test_binaries/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Google LLC 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License along 14 | # with this program; if not, write to the Free Software Foundation, Inc., 15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 | # 17 | 18 | if(NOT USE_DOCKER_BUILD) 19 | message(STATUS "USE_DOCKER_BUILD is not set. Skipping build process, and using prebuilt binaries instead.") 20 | 21 | add_test(NAME bn_llil_test 22 | COMMAND python3 bn_llil_test.py 23 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 24 | ) 25 | set_tests_properties(bn_llil_test PROPERTIES 26 | ENVIRONMENT "PYTHONPATH=${BN_INSTALL_DIR}/python;TEST_TARGET_FILE=${CMAKE_CURRENT_SOURCE_DIR}/prebuilt/bn_llil_test_app" 27 | ) 28 | 29 | add_test(NAME bn_hlil_test 30 | COMMAND python3 bn_hlil_test.py 31 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 32 | ) 33 | set_tests_properties(bn_hlil_test PROPERTIES 34 | ENVIRONMENT "PYTHONPATH=${BN_INSTALL_DIR}/python;TEST_TARGET_FILE=${CMAKE_CURRENT_SOURCE_DIR}/prebuilt/bn_hlil_test_app" 35 | ) 36 | else() 37 | # bn_llil_test 38 | set(BN_LLIL_TEST_BIN ${CMAKE_CURRENT_BINARY_DIR}/bn_llil_test) 39 | add_custom_command( 40 | OUTPUT ${BN_LLIL_TEST_BIN} 41 | COMMAND docker rm tmp-hexagon-llil-container 2>/dev/null || (exit 0) 42 | COMMAND docker build -t tmp-hexagon-llil-image -f build_llil_test.dockerfile . 43 | COMMAND docker run --name tmp-hexagon-llil-container tmp-hexagon-llil-image /bin/true 44 | COMMAND docker cp tmp-hexagon-llil-container:/build/bn_llil_test ${BN_LLIL_TEST_BIN} 45 | COMMAND docker rm tmp-hexagon-llil-container 2>/dev/null || (exit 0) 46 | COMMAND touch ${BN_LLIL_TEST_BIN} 47 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 48 | DEPENDS first.s bn_llil_test_app.s build_llil_test.dockerfile build_llil_test.makefile 49 | ) 50 | add_custom_target(bn_llil_test_app ALL 51 | DEPENDS ${BN_LLIL_TEST_BIN} 52 | ) 53 | 54 | add_test(NAME bn_llil_test 55 | COMMAND python3 bn_llil_test.py 56 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 57 | ) 58 | set_tests_properties(bn_llil_test PROPERTIES 59 | DEPENDS bn_llil_test_app 60 | ) 61 | set_tests_properties(bn_llil_test PROPERTIES 62 | ENVIRONMENT "PYTHONPATH=${BN_INSTALL_DIR}/python;TEST_TARGET_FILE=${BN_LLIL_TEST_BIN}" 63 | ) 64 | 65 | # bn_hlil_test 66 | set(BN_HLIL_TEST_BIN ${CMAKE_CURRENT_BINARY_DIR}/bn_hlil_test) 67 | add_custom_command( 68 | OUTPUT ${BN_HLIL_TEST_BIN} 69 | COMMAND docker rm tmp-hexagon-hlil-container 2>/dev/null || (exit 0) 70 | COMMAND docker build -t tmp-hexagon-hlil-image -f build_hlil_test.dockerfile . 71 | COMMAND docker run --name tmp-hexagon-hlil-container tmp-hexagon-hlil-image /bin/true 72 | COMMAND docker cp tmp-hexagon-hlil-container:/build/bn_hlil_test ${BN_HLIL_TEST_BIN} 73 | COMMAND docker rm tmp-hexagon-hlil-container 2>/dev/null || (exit 0) 74 | COMMAND touch ${BN_HLIL_TEST_BIN} 75 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 76 | DEPENDS bn_hlil_test_app.c build_hlil_test.dockerfile build_hlil_test.makefile 77 | ) 78 | add_custom_target(bn_hlil_test_app ALL 79 | DEPENDS ${BN_HLIL_TEST_BIN} 80 | ) 81 | 82 | add_test(NAME bn_hlil_test 83 | COMMAND python3 bn_hlil_test.py 84 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 85 | ) 86 | set_tests_properties(bn_hlil_test PROPERTIES 87 | DEPENDS bn_hlil_test_app 88 | ) 89 | set_tests_properties(bn_hlil_test PROPERTIES 90 | ENVIRONMENT "PYTHONPATH=${BN_INSTALL_DIR}/python;TEST_TARGET_FILE=${BN_HLIL_TEST_BIN}" 91 | ) 92 | 93 | endif() 94 | -------------------------------------------------------------------------------- /test_binaries/bn_hlil_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright (C) 2020 Google LLC 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along 16 | # with this program; if not, write to the Free Software Foundation, Inc., 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | 19 | import unittest 20 | import os 21 | 22 | try: 23 | import binaryninja as binja 24 | except ImportError: 25 | print('Failed to import binaryninja Python API.') 26 | print('Add ${BN_INSTALL_DIR}/python to PYTHONPATH.') 27 | sys.exit(1) 28 | 29 | 30 | # E2E test for Hexagon hlil plugin. 31 | # This test uses Binary Ninja headless API, analyses test_binaries/bn_hlil_test_app.s 32 | # and checks the HLIL output. 33 | class TestPluginIl(unittest.TestCase): 34 | TARGET_FILE = None 35 | 36 | @classmethod 37 | def setUpClass(cls): 38 | assert (cls.TARGET_FILE is not None) 39 | binja.log.log_to_stdout(True) 40 | cls.bv = binja.load(cls.TARGET_FILE) 41 | 42 | def get_function(self, name): 43 | return TestPluginIl.bv.get_functions_by_name(name)[0] 44 | 45 | def list_hlil(self, func): 46 | ret = [''] 47 | for line in func.hlil.root.lines: 48 | ret.append('{0}'.format(line)) 49 | return '\n'.join(ret) 50 | 51 | def test_add_int(self): 52 | func = self.get_function('test_add_int') 53 | self.assertEqual( 54 | self.list_hlil(func), ''' 55 | uint32_t temp0 = arg2 + arg1 56 | g_res = temp0 57 | return temp0''') 58 | 59 | def test_cmp_signed_int(self): 60 | func = self.get_function('test_cmp_signed_int') 61 | self.assertEqual( 62 | self.list_hlil(func), ''' 63 | bool temp90 = arg2 s> arg1 64 | uint32_t temp1 65 | if (temp90) 66 | temp1 = 0x8765 67 | if (not.b(temp90)) 68 | temp1 = 0x1234 69 | g_res = temp1''') 70 | 71 | def test_cmp_unsigned_int(self): 72 | func = self.get_function('test_cmp_unsigned_int') 73 | self.assertEqual( 74 | self.list_hlil(func), ''' 75 | bool temp90 = arg2 u> arg1 76 | uint32_t temp1 77 | if (temp90) 78 | temp1 = 0x8765 79 | if (not.b(temp90)) 80 | temp1 = 0x1234 81 | g_res = temp1''') 82 | 83 | def test_mul_int(self): 84 | func = self.get_function('test_mul_int') 85 | self.assertEqual( 86 | self.list_hlil(func), ''' 87 | uint32_t temp0 = arg2 * arg1 88 | g_res = temp0 89 | return temp0''') 90 | 91 | def test_func_call(self): 92 | func = self.get_function('test_func_call') 93 | self.assertEqual( 94 | self.list_hlil(func), ''' 95 | uint32_t R0 = arg1(arg2) 96 | g_res = R0 97 | return R0''') 98 | 99 | def test_struct(self): 100 | func = self.get_function('test_struct') 101 | self.assertEqual( 102 | self.list_hlil(func), ''' 103 | uint32_t temp0 = *(arg1 + 8) + arg2 104 | g_res = temp0 105 | return temp0''') 106 | 107 | def test_fact(self): 108 | func = self.get_function('test_fact') 109 | self.assertEqual( 110 | self.list_hlil(func), ''' 111 | char temp210 = 0 112 | if (arg1 != 0) 113 | temp210 = 1 114 | int32_t var_c 115 | if (temp210 != 1) 116 | var_c = 1 117 | else 118 | var_c = test_fact(arg1 - 1) * arg1 119 | return var_c''') 120 | 121 | def test_and_int(self): 122 | func = self.get_function('test_and_int') 123 | self.assertEqual( 124 | self.list_hlil(func), ''' 125 | uint32_t temp0 = arg2 & arg1 126 | g_res = temp0 127 | return temp0''') 128 | 129 | def test_or_int(self): 130 | func = self.get_function('test_or_int') 131 | self.assertEqual( 132 | self.list_hlil(func), ''' 133 | uint32_t temp0 = arg2 | arg1 134 | g_res = temp0 135 | return temp0''') 136 | 137 | def test_xor_int(self): 138 | func = self.get_function('test_xor_int') 139 | self.assertEqual( 140 | self.list_hlil(func), ''' 141 | uint32_t temp0 = arg2 ^ arg1 142 | g_res = temp0 143 | return temp0''') 144 | 145 | def test_not_int(self): 146 | func = self.get_function('test_not_int') 147 | self.assertEqual( 148 | self.list_hlil(func), ''' 149 | g_res = 0xffffffff - arg1 150 | return 0xffffffff - arg1''') 151 | 152 | def test_collatz(self): 153 | func = self.get_function('test_collatz') 154 | self.assertEqual( 155 | self.list_hlil(func), ''' 156 | int32_t var_c = arg1 157 | while (true) 158 | char temp210_1 = 0 159 | if (var_c == 1) 160 | temp210_1 = 1 161 | if (temp210_1 == 1) 162 | break 163 | char temp210_2 = 0 164 | if ((var_c & 1) != 0) 165 | temp210_2 = 1 166 | if (temp210_2 == 1) 167 | var_c = 1 + var_c * 3 168 | else 169 | var_c = var_c s>> 1 170 | return var_c''') 171 | 172 | def test_max_signed_int(self): 173 | func = self.get_function('test_max_signed_int') 174 | self.assertEqual( 175 | self.list_hlil(func), ''' 176 | int32_t temp0 = (arg1 s>= arg2 ? 1 : 0) * arg1 + (arg1 s< arg2 ? 1 : 0) * arg2 177 | g_res = temp0 178 | return temp0''') 179 | 180 | def test_max_unsigned_int(self): 181 | func = self.get_function('test_max_unsigned_int') 182 | self.assertEqual( 183 | self.list_hlil(func), ''' 184 | int32_t temp0 = (arg1 u>= arg2 ? 1 : 0) * arg1 + (arg1 u< arg2 ? 1 : 0) * arg2 185 | g_res = temp0 186 | return temp0''') 187 | 188 | def test_min_signed_int(self): 189 | func = self.get_function('test_min_signed_int') 190 | self.assertEqual( 191 | self.list_hlil(func), ''' 192 | int32_t temp0 = (arg1 s<= arg2 ? 1 : 0) * arg1 + (arg1 s> arg2 ? 1 : 0) * arg2 193 | g_res = temp0 194 | return temp0''') 195 | 196 | def test_min_unsigned_int(self): 197 | func = self.get_function('test_min_unsigned_int') 198 | self.assertEqual( 199 | self.list_hlil(func), ''' 200 | int32_t temp0 = (arg1 u<= arg2 ? 1 : 0) * arg1 + (arg1 u> arg2 ? 1 : 0) * arg2 201 | g_res = temp0 202 | return temp0''') 203 | 204 | 205 | if __name__ == '__main__': 206 | TestPluginIl.TARGET_FILE = os.environ.get('TEST_TARGET_FILE') 207 | unittest.main() 208 | -------------------------------------------------------------------------------- /test_binaries/bn_hlil_test_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 23 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 24 | 25 | static int g_res = 0; 26 | 27 | __attribute__((noinline)) void test_add_int(int a, int b) { g_res = a + b; } 28 | 29 | __attribute__((noinline)) void test_cmp_signed_int(int a, int b) { 30 | g_res = (a >= b ? 0x1234 : 0x8765); 31 | } 32 | 33 | __attribute__((noinline)) void test_cmp_unsigned_int(unsigned int a, 34 | unsigned int b) { 35 | g_res = (a >= b ? 0x1234 : 0x8765); 36 | } 37 | 38 | __attribute__((noinline)) void test_mul_int(int a, int b) { g_res = a * b; } 39 | 40 | __attribute__((noinline)) void test_func_call(int a, int b) { 41 | typedef int (*FUNC)(int); 42 | FUNC p = (FUNC)a; 43 | g_res = p(b); 44 | } 45 | 46 | __attribute__((noinline)) void test_struct(int a, int b) { 47 | typedef struct { 48 | int x[2]; 49 | int y; 50 | } STRUCT; 51 | STRUCT *p = (STRUCT *)a; 52 | g_res = p->y + b; 53 | } 54 | 55 | __attribute__((noinline)) __attribute__((optnone)) int test_fact(int a) { 56 | if (a == 0) 57 | return 1; 58 | return test_fact(a - 1) * a; 59 | } 60 | 61 | __attribute__((noinline)) void test_and_int(int a, int b) { g_res = a & b; } 62 | __attribute__((noinline)) void test_or_int(int a, int b) { g_res = a | b; } 63 | __attribute__((noinline)) void test_xor_int(int a, int b) { g_res = a ^ b; } 64 | __attribute__((noinline)) void test_not_int(int a) { g_res = ~a; } 65 | __attribute__((noinline)) __attribute__((optnone)) void test_collatz(int a) { 66 | while (a != 1) { 67 | if ((a & 1) == 0) { 68 | a = a >> 1; 69 | } else { 70 | a = 3 * a + 1; 71 | } 72 | } 73 | } 74 | 75 | __attribute__((noinline)) void test_max_signed_int(int a, int b) { 76 | g_res = MAX(a, b); 77 | } 78 | 79 | __attribute__((noinline)) void test_max_unsigned_int(unsigned int a, 80 | unsigned int b) { 81 | g_res = MAX(a, b); 82 | } 83 | 84 | __attribute__((noinline)) void test_min_signed_int(int a, int b) { 85 | g_res = MIN(a, b); 86 | } 87 | 88 | __attribute__((noinline)) void test_min_unsigned_int(unsigned int a, 89 | unsigned int b) { 90 | g_res = MIN(a, b); 91 | } 92 | 93 | int main(int argc, char *argv[]) { 94 | test_add_int(argc, argc + 1); 95 | test_cmp_signed_int(argc, argc + 1); 96 | test_cmp_unsigned_int(argc, argc + 1); 97 | test_mul_int(argc, argc + 1); 98 | test_func_call(argc, argc + 1); 99 | test_struct(argc, argc + 1); 100 | test_fact(argc); 101 | test_and_int(argc, argc + 1); 102 | test_or_int(argc, argc + 1); 103 | test_xor_int(argc, argc + 1); 104 | test_not_int(argc); 105 | test_collatz(argc); 106 | test_max_signed_int(argc, argc + 1); 107 | test_max_unsigned_int(argc, argc + 1); 108 | test_min_signed_int(argc, argc + 1); 109 | test_min_unsigned_int(argc, argc + 1); 110 | return g_res; 111 | } 112 | -------------------------------------------------------------------------------- /test_binaries/bn_llil_test_app.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | .text 20 | .globl start 21 | 22 | test_allocframe: 23 | { allocframe(r29,#8):raw } 24 | { r0=#256 } 25 | { dealloc_return } 26 | 27 | test_pair_operations: 28 | { r5:4=add(r3:2,r9:8) } 29 | { jumpr lr } 30 | 31 | test_cmp_to_predicate: 32 | { p0 = cmp.eq(r0,#1) } 33 | { jumpr lr } 34 | 35 | test_memory_load: 36 | { r1=##buffer } 37 | { r2=memb(r1+#1) } 38 | { jumpr lr } 39 | 40 | test_memory_store: 41 | { memw(r1)=#1193046 } 42 | { jumpr lr } 43 | 44 | test_store_dotnew: 45 | { r3=add(r1,r2) 46 | memw(r5) = r3.new } 47 | { jumpr lr } 48 | 49 | test_mux: 50 | { r0 = mux(p0,#1,#0) } 51 | { jumpr lr } 52 | 53 | test_tstbit: 54 | { p0 = tstbit(r0,#0) } 55 | { jumpr lr } 56 | 57 | // 58 | // Test for dual jump instructions (Table 8-12). 59 | // 60 | // Direct jump: 61 | // first jump in packet: No 62 | // second jump in packet: Yes 63 | test_dualjump_direct_jump: 64 | { r1 = add(r1, r1) 65 | jump 1f } 66 | { nop } 67 | 1: 68 | { r0 = #1 69 | jumpr r31 } 70 | 71 | // Conditional jump: 72 | // first jump in packet: Yes 73 | // second jump in packet: Yes 74 | test_dualjump_cond_jump: 75 | { r1 = add(r1, r1) 76 | if (p0) jump:t 1f } 77 | { r0 = #0 78 | jumpr r31 } 79 | 1: 80 | { r0 = #1 81 | jumpr r31 } 82 | 83 | test_dualjump_cond_jump_with_direct_jump: 84 | { r1 = add(r1, r1) 85 | if (p0) jump:t 1f 86 | jump 2f } 87 | 1: 88 | { r0 = #1 89 | jumpr r31 } 90 | 2: 91 | { r0 = #2 92 | jumpr r31 } 93 | 94 | test_dualjump_two_cond_jumps: 95 | { r1 = add(r1, r1) 96 | if (p0) jump:t 1f 97 | if (!p1) jump:t 2f } 98 | { r0 = #0 99 | jumpr r31 } 100 | 1: 101 | { r0 = #1 102 | jumpr r31 } 103 | 2: 104 | { r1 = #2 105 | jumpr r31 } 106 | 107 | // Direct calls: 108 | // first jump in packet: No 109 | // second jump in packet: Yes 110 | test_dualjump_direct_call: 111 | { r0 = add(r1,r0) 112 | call 1f } 113 | 114 | { nop 115 | jumpr r31 } 116 | 1: 117 | { r0 = #1 118 | jumpr r31 } 119 | 120 | test_dualjump_direct_call_reorder: 121 | { call 1f 122 | memw(r2+#0) = r3 } 123 | 124 | { nop 125 | jumpr r31 } 126 | 1: 127 | { r0 = #1 128 | jumpr r31 } 129 | 130 | test_dualjump_cond_call: 131 | { r1 = add(r1, r1) 132 | if (p0) call 1f } 133 | { r0 = #0 134 | jumpr r31 } 135 | 1: 136 | { r0 = #1 137 | jumpr r31 } 138 | 139 | test_dualjump_cond_call_with_direct_jump: 140 | { r1 = add(r1, r1) 141 | if (p0) call 1f 142 | jump 2f } 143 | 1: 144 | { r0 = #1 145 | jumpr r31 } 146 | 2: 147 | { r0 = #2 148 | jumpr r31 } 149 | 150 | // Compare jump: 151 | // first jump in packet: Yes 152 | // second jump in packet: Yes 153 | test_dualjump_cmp_jump: 154 | { r1 = add(r1, r1) 155 | p0 = cmp.eq(r3, #2); if (p0.new) jump:t 1f } 156 | { r0 = #0 157 | jumpr r31 } 158 | 1: 159 | { r0 = #1 160 | jumpr r31 } 161 | 162 | test_dualjump_cmp_jump_with_direct_jump: 163 | { r1 = add(r1, r1) 164 | p0 = cmp.eq(r3, #2); if (p0.new) jump:t 1f 165 | jump 2f } 166 | 1: 167 | { r0 = #1 168 | jumpr r31 } 169 | 2: 170 | { r0 = #2 171 | jumpr r31 } 172 | 173 | test_dualjump_two_cmp_jumps: 174 | { r1 = add(r1, r1) 175 | p0 = cmp.eq(r3, #2); if (p0.new) jump:t 1f 176 | p1 = cmp.eq(r3, #2); if (p1.new) jump:t 2f } 177 | { r0 = #0 178 | jumpr r31 } 179 | 1: 180 | { r0 = #1 181 | jumpr r31 } 182 | 2: 183 | { r0 = #2 184 | jumpr r31 } 185 | 186 | // New-value compare jump: 187 | // first jump in packet: No 188 | // second jump in packet: No 189 | test_dualjump_newval_cmp_jump: 190 | { r1 = add(r1, r1) 191 | if (cmp.eq(r1.new, r2)) jump:t 1f } 192 | { r0 = #0 193 | jumpr r31 } 194 | 1: 195 | { r0 = #1 196 | jumpr r31 } 197 | 198 | // Indirect jumps: 199 | // first jump in packet: No 200 | // second jump in packet: No 201 | test_dualjump_indirect_jump: 202 | { r1 = add(r1, r1) 203 | jumpr r0 } 204 | 205 | test_dualjump_indirect_jump_reorder: 206 | { jumpr r0 207 | r1 = add(r1, r1) } 208 | 209 | test_dualjump_cond_indirect_jump: 210 | { r1 = add(r1, r1) 211 | if (p0) jumpr r0 } 212 | { r0 = #0 213 | jumpr r31 } 214 | 215 | // Indirect calls: 216 | // first jump in packet: No 217 | // second jump in packet: No 218 | test_dualjump_indirect_call: 219 | { r1 = add(r1, r1) 220 | callr r0 } 221 | 222 | test_dualjump_cond_indirect_call: 223 | { r1 = add(r1, r1) 224 | if (p0) callr r0 } 225 | { r0 = #0 226 | jumpr r31 } 227 | 228 | 229 | // dealloc_return: 230 | // first jump in packet: No 231 | // second jump in packet: No 232 | test_dualjump_cond_return: 233 | { r1 = add(r1, r1) 234 | if (p0) dealloc_return } 235 | { r0 = #0 236 | jumpr r31 } 237 | 238 | test_hwloop: 239 | { loop0(1f, #10) 240 | r1 = #0 } 241 | 242 | 1: 243 | { r1 = add(r1, #1) 244 | nop 245 | }:endloop0 246 | 247 | { jumpr lr } 248 | 249 | test_control_regs: 250 | { p0 = cmp.eq(r0, #1) } 251 | { r1 = c4 } 252 | { jumpr lr } 253 | 254 | test_halfwords: 255 | { r0.h = #12 256 | r1.l = #34 } 257 | { jumpr lr } 258 | 259 | test_insert: 260 | { r1 = insert(r0, #1, #6) } 261 | { jumpr lr } 262 | 263 | test_extract: 264 | { r1 = extractu(r0, #2, #20) } 265 | { jumpr lr } 266 | 267 | test_global_pointer_relative_offset: 268 | { r1 = memw(gp + #16) } 269 | { jumpr lr } 270 | 271 | test_global_pointer_relative_imm: 272 | { r1 = memw(#16) } 273 | { jumpr lr } 274 | 275 | test_global_pointer_relative_immext: 276 | { r1 = memw(##0x123450) } 277 | { jumpr lr } 278 | 279 | test_swiz: 280 | { r1 = swiz(r0) } 281 | { jumpr lr } 282 | 283 | test_combine_zero_and_reg: 284 | { r0 = #1 } 285 | { r3:2 = combine(#0, r0) } 286 | { jumpr lr } 287 | 288 | test_combine_reg_and_zero: 289 | { r0 = #1 } 290 | { r3:2 = combine(r0, #0) } 291 | { jumpr lr } 292 | 293 | test_combine_imms: 294 | { r3:2 = combine(#1, ##buffer) } 295 | { jumpr lr } 296 | 297 | test_combine_regs: 298 | { r0 = #1 299 | r1 = #2 } 300 | { r3:2 = combine(r0, r1) } 301 | { jumpr lr } 302 | 303 | test_rol: 304 | { r5 = rol(r1,#0x1c) } 305 | { jumpr lr } 306 | 307 | test_rol_pair: 308 | { r5:4 = rol(r1:0,#0xc) } 309 | { jumpr lr } 310 | 311 | // https://github.com/google/binja-hexagon/issues/5 regression test. 312 | test_clobbered_pair: 313 | { R17:16 = combine(R0,R1) 314 | memd(SP+#0xfffffff0) = R17:16; allocframe(#0x18) } 315 | { jumpr lr } 316 | 317 | // https://github.com/google/binja-hexagon/issues/10 regression test. 318 | // See https://github.com/qemu/qemu/commit/07c0f65385b9. 319 | test_lsbnew: 320 | { r0 = #2 } 321 | { r1 = #5 } 322 | { p0 = r0 323 | if (p0.new) r1 = #3 324 | } 325 | { r0 = r1 } 326 | { jumpr lr } 327 | 328 | start: 329 | { call test_allocframe } 330 | { call test_pair_operations } 331 | { call test_cmp_to_predicate } 332 | { call test_memory_load } 333 | { call test_memory_store } 334 | { call test_store_dotnew } 335 | { call test_mux } 336 | { call test_tstbit } 337 | { call test_dualjump_direct_jump } 338 | { call test_dualjump_cond_jump } 339 | { call test_dualjump_cond_jump_with_direct_jump } 340 | { call test_dualjump_two_cond_jumps } 341 | { call test_dualjump_direct_call } 342 | { call test_dualjump_direct_call_reorder } 343 | { call test_dualjump_cond_call } 344 | { call test_dualjump_cond_call_with_direct_jump } 345 | { call test_dualjump_cmp_jump } 346 | { call test_dualjump_cmp_jump_with_direct_jump } 347 | { call test_dualjump_two_cmp_jumps } 348 | { call test_dualjump_newval_cmp_jump } 349 | { call test_dualjump_indirect_jump } 350 | { call test_dualjump_indirect_jump_reorder } 351 | { call test_dualjump_cond_indirect_jump } 352 | { call test_dualjump_indirect_call } 353 | { call test_dualjump_cond_indirect_call } 354 | { call test_dualjump_cond_return } 355 | { call test_hwloop } 356 | { call test_control_regs } 357 | { call test_halfwords } 358 | { call test_insert } 359 | { call test_extract } 360 | { call test_global_pointer_relative_offset } 361 | { call test_global_pointer_relative_imm } 362 | { call test_global_pointer_relative_immext } 363 | { call test_swiz } 364 | { call test_combine_zero_and_reg } 365 | { call test_combine_reg_and_zero } 366 | { call test_combine_imms } 367 | { call test_combine_regs } 368 | { call test_rol } 369 | { call test_rol_pair } 370 | { call test_clobbered_pair } 371 | { call test_lsbnew } 372 | 373 | { jumpr lr } 374 | 375 | 376 | .data 377 | .globl buffer 378 | .p2align 8 379 | buffer: 380 | .string "Hello world!\n" 381 | .size buffer, 14 382 | -------------------------------------------------------------------------------- /test_binaries/build_hlil_test.dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.gitlab.com/qemu-project/qemu/qemu/debian-hexagon-cross:latest as build 2 | 3 | RUN mkdir /build 4 | COPY build_hlil_test.makefile /build/Makefile 5 | COPY bn_hlil_test_app.c /build 6 | RUN make -C /build bn_hlil_test 7 | 8 | CMD sleep 1 9 | -------------------------------------------------------------------------------- /test_binaries/build_hlil_test.makefile: -------------------------------------------------------------------------------- 1 | CC=hexagon-unknown-linux-musl-clang 2 | CFLAGS=-mv67 -O2 -mhvx -Wall -g -fPIC -shared 3 | LDFLAGS=-shared 4 | 5 | %.o : %.s 6 | $(CC) -c $(CFLAGS) $< -o $@ 7 | 8 | bn_hlil_test: bn_hlil_test_app.o 9 | $(CC) $^ -o $@ $(LDFLAGS) 10 | 11 | -------------------------------------------------------------------------------- /test_binaries/build_llil_test.dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.gitlab.com/qemu-project/qemu/qemu/debian-hexagon-cross:latest as build 2 | 3 | RUN mkdir /build 4 | COPY build_llil_test.makefile /build/Makefile 5 | COPY bn_llil_test_app.s /build 6 | COPY first.s /build 7 | RUN make -C /build bn_llil_test 8 | 9 | CMD sleep 1 10 | -------------------------------------------------------------------------------- /test_binaries/build_llil_test.makefile: -------------------------------------------------------------------------------- 1 | CC=hexagon-unknown-linux-musl-clang 2 | CFLAGS=-mv67 -O2 -mhvx -Wall -g 3 | LDFLAGS=-static -nostdlib -e start 4 | ASM=-S 5 | 6 | %.o : %.s 7 | $(CC) -c $(CFLAGS) $< -o $@ 8 | 9 | bn_llil_test: first.o bn_llil_test_app.o 10 | $(CC) $^ -o $@ $(LDFLAGS) 11 | 12 | -------------------------------------------------------------------------------- /test_binaries/first.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Google LLC 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | .section ".note.ABI-tag", "a" 20 | .align 4 21 | .long 1f - 0f /* name length */ 22 | .long 3f - 2f /* data length */ 23 | .long 1 /* note type */ 24 | 25 | /* 26 | * vendor name seems like this should be MUSL but lldb doesn't agree. 27 | */ 28 | 0: .asciz "GNU" 29 | 1: .align 4 30 | 2: .long 0 /* linux */ 31 | .long 3,0,0 32 | 3: .align 4 33 | -------------------------------------------------------------------------------- /test_binaries/prebuilt/bn_hlil_test_app: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/binja-hexagon/28049a80b7e3e1aba142466cf0dbeb5ba7c396a8/test_binaries/prebuilt/bn_hlil_test_app -------------------------------------------------------------------------------- /test_binaries/prebuilt/bn_llil_test_app: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/binja-hexagon/28049a80b7e3e1aba142466cf0dbeb5ba7c396a8/test_binaries/prebuilt/bn_llil_test_app -------------------------------------------------------------------------------- /third_party/chromium/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(blink) 2 | -------------------------------------------------------------------------------- /third_party/chromium/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /third_party/chromium/blink/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(interval_map 2 | INTERFACE 3 | ) 4 | 5 | add_executable(interval_map_test 6 | interval_map_unittest.cc 7 | ) 8 | 9 | target_link_libraries(interval_map_test 10 | interval_map 11 | gmock 12 | glog 13 | gtest_main 14 | absl::base 15 | absl::strings 16 | absl::str_format 17 | ) 18 | 19 | add_test(interval_map_test interval_map_test) 20 | add_dependencies(check interval_map_test) 21 | -------------------------------------------------------------------------------- /third_party/gflags_CMakeLists.txt.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.0) 2 | project ("gflags-build" C CXX) 3 | include(FindPackageHandleStandardArgs) 4 | find_package(Threads REQUIRED) 5 | set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) 6 | set(GFLAGS_BUILD_SHARED_LIBS OFF) 7 | set(GFLAGS_BUILD_STATIC_LIBS ON) 8 | set(GFLAGS_BUILD_gflags_LIB ON) 9 | set(GFLAGS_BUILD_gflags_nothreads_LIB OFF) 10 | set(GFLAGS_BUILD_TESTING OFF) 11 | set(GFLAGS_BUILD_PACKAGING OFF) 12 | add_subdirectory(${CMAKE_SOURCE_DIR}/third_party/gflags 13 | ${CMAKE_BINARY_DIR}/gflags-build/build 14 | ) 15 | 16 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Step 1 3 | # We use a C program to create semantics_generated.pyinc 4 | # 5 | add_executable(gen_semantics 6 | gen_semantics.c 7 | ) 8 | 9 | set(SEMANTICS ${CMAKE_CURRENT_BINARY_DIR}/semantics_generated.pyinc) 10 | set(SEMANTICS ${SEMANTICS} PARENT_SCOPE) 11 | add_custom_command( 12 | OUTPUT ${SEMANTICS} 13 | COMMAND $ ${SEMANTICS} 14 | ) 15 | 16 | # 17 | # Step 2 18 | # We use Python scripts to generate the following files 19 | # 20 | set(OPCODES_DEF_H ${CMAKE_CURRENT_BINARY_DIR}/opcodes_def_generated.h) 21 | set(OP_REGS_H ${CMAKE_CURRENT_BINARY_DIR}/op_regs_generated.h) 22 | set(OP_ATTRIBS_H ${CMAKE_CURRENT_BINARY_DIR}/op_attribs_generated.h) 23 | set(SHORTCODE_H ${CMAKE_CURRENT_BINARY_DIR}/shortcode_generated.h) 24 | 25 | add_custom_command( 26 | OUTPUT ${OPCODES_DEF_H} 27 | COMMAND python3 gen_opcodes_def.py ${SEMANTICS} attribs_def.h ${OPCODES_DEF_H} 28 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 29 | DEPENDS hex_common.py gen_opcodes_def.py ${SEMANTICS} attribs_def.h 30 | ) 31 | 32 | add_custom_command( 33 | OUTPUT ${OP_REGS_H} 34 | COMMAND python3 gen_op_regs.py ${SEMANTICS} attribs_def.h ${OP_REGS_H} 35 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 36 | DEPENDS hex_common.py gen_op_regs.py ${SEMANTICS} attribs_def.h 37 | ) 38 | 39 | add_custom_command( 40 | OUTPUT ${OP_ATTRIBS_H} 41 | COMMAND python3 gen_op_attribs.py ${SEMANTICS} attribs_def.h ${OP_ATTRIBS_H} 42 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 43 | DEPENDS hex_common.py gen_op_attribs.py ${SEMANTICS} attribs_def.h 44 | ) 45 | 46 | add_custom_command( 47 | OUTPUT ${SHORTCODE_H} 48 | COMMAND python3 gen_shortcode.py ${SEMANTICS} attribs_def.h ${SHORTCODE_H} 49 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 50 | DEPENDS hex_common.py gen_shortcode.py ${SEMANTICS} attribs_def.h 51 | ) 52 | 53 | # 54 | # Step 3 55 | # We use a C program to create iset.py which is imported into dectree.py 56 | # to create the decode tree 57 | # 58 | 59 | add_executable(gen_dectree_import 60 | gen_dectree_import.c 61 | ) 62 | 63 | target_include_directories(gen_dectree_import 64 | PRIVATE 65 | ${CMAKE_CURRENT_BINARY_DIR} 66 | ) 67 | 68 | add_custom_target(gen_opcodes_def_h 69 | DEPENDS ${OPCODES_DEF_H} ${OP_REGS_H} 70 | ) 71 | add_dependencies(gen_dectree_import 72 | gen_opcodes_def_h 73 | ) 74 | 75 | set(DECTREE_IMPORT ${CMAKE_CURRENT_BINARY_DIR}/iset.py) 76 | add_custom_command( 77 | OUTPUT ${DECTREE_IMPORT} 78 | COMMAND $ ${DECTREE_IMPORT} 79 | ) 80 | 81 | # 82 | # Step 4 83 | # We use the dectree.py script to generate the decode tree header file 84 | # 85 | set(DECTREE_HEADER ${CMAKE_CURRENT_BINARY_DIR}/dectree_generated.h) 86 | add_custom_command( 87 | OUTPUT ${DECTREE_HEADER} 88 | COMMAND PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR} python3 dectree.py ${DECTREE_HEADER} 89 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 90 | DEPENDS dectree.py ${DECTREE_IMPORT} 91 | ) 92 | 93 | 94 | # 95 | # Special deps and interface targets. 96 | # 97 | set(GENERATED_HEXAGON_FILES 98 | ${OPCODES_DEF_H} 99 | ${OP_REGS_H} 100 | ${OP_ATTRIBS_H} 101 | ${SHORTCODE_H} 102 | ${DECTREE_HEADER} 103 | ) 104 | 105 | add_custom_target(hexagon_generated_headers_deps 106 | DEPENDS ${GENERATED_HEXAGON_FILES} 107 | ) 108 | 109 | add_library(hexagon_generated_headers_interface 110 | INTERFACE 111 | ) 112 | 113 | target_include_directories(hexagon_generated_headers_interface 114 | INTERFACE 115 | ${CMAKE_CURRENT_BINARY_DIR} 116 | ) 117 | 118 | # 119 | # Decoder library. 120 | # 121 | add_library(decoder_c_lib 122 | decode_ext_mmvec.c 123 | decode.c 124 | iclass.c 125 | opcodes.c 126 | reg_fields.c 127 | ) 128 | 129 | target_link_libraries(decoder_c_lib 130 | hexagon_generated_headers_interface 131 | ) 132 | 133 | add_dependencies(decoder_c_lib 134 | hexagon_generated_headers_deps 135 | ) 136 | 137 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/LICENSE: -------------------------------------------------------------------------------- 1 | The QEMU distribution includes both the QEMU emulator and 2 | various firmware files. These are separate programs that are 3 | distributed together for our users' convenience, and they have 4 | separate licenses. 5 | 6 | The following points clarify the license of the QEMU emulator: 7 | 8 | 1) The QEMU emulator as a whole is released under the GNU General 9 | Public License, version 2. 10 | 11 | 2) Parts of the QEMU emulator have specific licenses which are compatible 12 | with the GNU General Public License, version 2. Hence each source file 13 | contains its own licensing information. Source files with no licensing 14 | information are released under the GNU General Public License, version 15 | 2 or (at your option) any later version. 16 | 17 | As of July 2013, contributions under version 2 of the GNU General Public 18 | License (and no later version) are only accepted for the following files 19 | or directories: bsd-user/, linux-user/, hw/vfio/, hw/xen/xen_pt*. 20 | 21 | 3) The Tiny Code Generator (TCG) is mostly under the BSD or MIT licenses; 22 | but some parts may be GPLv2 or other licenses. Again, see the 23 | specific licensing information in each source file. 24 | 25 | 4) QEMU is a trademark of Fabrice Bellard. 26 | 27 | Fabrice Bellard and the QEMU team 28 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/README.md: -------------------------------------------------------------------------------- 1 | # QEMU Hexagon Target 2 | 3 | This folder is a modified version of [quic/qemu](https://github.com/quic/qemu) Hexagon target. 4 | 5 | Local changes include: 6 | 7 | * Added new attribute annotations: `A_BN_COND_J`, `A_BN_RETURN`, `A_BN_SYSTEM`. 8 | 9 | * Replaces `assert`s with `longjmp`s, so decoder fails gracefully for invalid, non-code input. 10 | 11 | * Removed QEMU specific code (`gen_tcg_funcs.py`). 12 | 13 | * Removed QEMU library dependencies. 14 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/attribs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | enum { 25 | #define DEF_ATTRIB(NAME, ...) A_##NAME, 26 | #include "third_party/qemu-hexagon/attribs_def.h" 27 | #undef DEF_ATTRIB 28 | }; 29 | 30 | #define GET_ATTRIB(opcode, attrib) test_bit(attrib, opcode_attribs[opcode]) 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/attribs_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* Keep this as the first attribute: */ 19 | DEF_ATTRIB(AA_DUMMY, "Dummy Zeroth Attribute", "", "") 20 | 21 | /* Misc */ 22 | DEF_ATTRIB(EXTENSION, "Extension instruction", "", "") 23 | 24 | DEF_ATTRIB(PRIV, "Not available in user or guest mode", "", "") 25 | DEF_ATTRIB(GUEST, "Not available in user mode", "", "") 26 | 27 | DEF_ATTRIB(FPOP, "Floating Point Operation", "", "") 28 | 29 | DEF_ATTRIB(EXTENDABLE, "Immediate may be extended", "", "") 30 | 31 | DEF_ATTRIB(ARCHV2, "V2 architecture", "", "") 32 | DEF_ATTRIB(ARCHV3, "V3 architecture", "", "") 33 | DEF_ATTRIB(ARCHV4, "V4 architecture", "", "") 34 | DEF_ATTRIB(ARCHV5, "V5 architecture", "", "") 35 | 36 | DEF_ATTRIB(SUBINSN, "sub-instruction", "", "") 37 | 38 | /* Load and Store attributes */ 39 | DEF_ATTRIB(LOAD, "Loads from memory", "", "") 40 | DEF_ATTRIB(STORE, "Stores to memory", "", "") 41 | DEF_ATTRIB(MEMLIKE, "Memory-like instruction", "", "") 42 | DEF_ATTRIB(MEMLIKE_PACKET_RULES, "follows Memory-like packet rules", "", "") 43 | 44 | /* V6 Vector attributes */ 45 | DEF_ATTRIB(CVI, "Executes on the HVX extension", "", "") 46 | 47 | DEF_ATTRIB(CVI_NEW, "New value memory instruction executes on HVX", "", "") 48 | DEF_ATTRIB(CVI_VM, "Memory instruction executes on HVX", "", "") 49 | DEF_ATTRIB(CVI_VP, "Permute instruction executes on HVX", "", "") 50 | DEF_ATTRIB(CVI_VP_VS, "Double vector permute/shft insn executes on HVX", "", "") 51 | DEF_ATTRIB(CVI_VX, "Multiply instruction executes on HVX", "", "") 52 | DEF_ATTRIB(CVI_VX_DV, "Double vector multiply insn executes on HVX", "", "") 53 | DEF_ATTRIB(CVI_VS, "Shift instruction executes on HVX", "", "") 54 | DEF_ATTRIB(CVI_VS_VX, "Permute/shift and multiply insn executes on HVX", "", "") 55 | DEF_ATTRIB(CVI_VA, "ALU instruction executes on HVX", "", "") 56 | DEF_ATTRIB(CVI_VA_DV, "Double vector alu instruction executes on HVX", "", "") 57 | DEF_ATTRIB(CVI_4SLOT, "Consumes all the vector execution resources", "", "") 58 | DEF_ATTRIB(CVI_TMP, "Transient Memory Load not written to register", "", "") 59 | DEF_ATTRIB(CVI_GATHER, "CVI Gather operation", "", "") 60 | DEF_ATTRIB(CVI_SCATTER, "CVI Scatter operation", "", "") 61 | DEF_ATTRIB(CVI_SCATTER_RELEASE, "CVI Store Release for scatter", "", "") 62 | DEF_ATTRIB(CVI_TMP_DST, "CVI instruction that doesn't write a register", "", "") 63 | DEF_ATTRIB(CVI_SLOT23, "Can execute in slot 2 or slot 3 (HVX)", "", "") 64 | 65 | /* Change-of-flow attributes */ 66 | DEF_ATTRIB(JUMP, "Jump-type instruction", "", "") 67 | DEF_ATTRIB(INDIRECT, "Absolute register jump", "", "") 68 | DEF_ATTRIB(CALL, "Function call instruction", "", "") 69 | DEF_ATTRIB(COF, "Change-of-flow instruction", "", "") 70 | DEF_ATTRIB(CONDEXEC, "May be cancelled by a predicate", "", "") 71 | DEF_ATTRIB(DOTNEWVALUE, "Uses a register value generated in this pkt", "", "") 72 | DEF_ATTRIB(NEWCMPJUMP, "Compound compare and jump", "", "") 73 | 74 | /* access to implicit registers */ 75 | DEF_ATTRIB(IMPLICIT_WRITES_LR, "Writes the link register", "", "UREG.LR") 76 | DEF_ATTRIB(IMPLICIT_WRITES_SP, "Writes the stack pointer", "", "UREG.SP") 77 | DEF_ATTRIB(IMPLICIT_WRITES_FP, "Writes the frame pointer", "", "UREG.FP") 78 | DEF_ATTRIB(IMPLICIT_WRITES_LC0, "Writes loop count for loop 0", "", "UREG.LC0") 79 | DEF_ATTRIB(IMPLICIT_WRITES_LC1, "Writes loop count for loop 1", "", "UREG.LC1") 80 | DEF_ATTRIB(IMPLICIT_WRITES_SA0, "Writes start addr for loop 0", "", "UREG.SA0") 81 | DEF_ATTRIB(IMPLICIT_WRITES_SA1, "Writes start addr for loop 1", "", "UREG.SA1") 82 | DEF_ATTRIB(IMPLICIT_WRITES_P0, "Writes Predicate 0", "", "UREG.P0") 83 | DEF_ATTRIB(IMPLICIT_WRITES_P1, "Writes Predicate 1", "", "UREG.P1") 84 | DEF_ATTRIB(IMPLICIT_WRITES_P2, "Writes Predicate 1", "", "UREG.P2") 85 | DEF_ATTRIB(IMPLICIT_WRITES_P3, "May write Predicate 3", "", "UREG.P3") 86 | DEF_ATTRIB(IMPLICIT_WRITES_SGP0, "Reads the SGP0 register", "", "MREG.SGP0") 87 | DEF_ATTRIB(IMPLICIT_WRITES_SGP1, "Reads the SGP1 register", "", "MREG.SGP1") 88 | DEF_ATTRIB(IMPLICIT_WRITES_STID_PRIO_ANYTHREAD, "Reads", "", "MREG.STID.PRIO") 89 | DEF_ATTRIB(IMPLICIT_WRITES_CCR, "May write CCR values", "", "MREG.CCR") 90 | DEF_ATTRIB(IMPLICIT_WRITES_SSR, "May write SSR values", "", "MREG.SSR") 91 | DEF_ATTRIB(IMPLICIT_WRITES_GELR, "May write GELR values", "", "GREG.GELR") 92 | DEF_ATTRIB(IMPLICIT_WRITES_GSR, "May write GSR values", "", "GREG.GSR") 93 | DEF_ATTRIB(IMPLICIT_WRITES_GOSP, "May write GOSP values", "", "GREG.GOSP") 94 | DEF_ATTRIB(IMPLICIT_WRITES_IPENDAD_IPEND, "May write", "", "MREG.IPENDAD.IPEND") 95 | DEF_ATTRIB(IMPLICIT_WRITES_IPENDAD_IAD, "May write", "", "MREG.IPENDAD.IAD") 96 | DEF_ATTRIB(IMPLICIT_WRITES_IMASK_ANYTHREAD, "May write", "", "MREG.IMASK") 97 | DEF_ATTRIB(IMPLICIT_WRITES_SYSCFG_GCA, "May write", "", "MREG.SYSCFG.GCA") 98 | 99 | DEF_ATTRIB(CRSLOT23, "Can execute in slot 2 or slot 3 (CR)", "", "") 100 | DEF_ATTRIB(IT_NOP, "nop instruction", "", "") 101 | DEF_ATTRIB(IT_EXTENDER, "constant extender instruction", "", "") 102 | 103 | /* Exceptions the instruction can generate */ 104 | 105 | DEF_ATTRIB(EXCEPTION_SWI, "Software Interrupt (trap) exception", "", "") 106 | 107 | /* Restrictions to make note of */ 108 | DEF_ATTRIB(RESTRICT_SLOT0ONLY, "Must execute on slot0", "", "") 109 | DEF_ATTRIB(RESTRICT_SLOT1ONLY, "Must execute on slot1", "", "") 110 | DEF_ATTRIB(RESTRICT_SLOT2ONLY, "Must execute on slot2", "", "") 111 | DEF_ATTRIB(RESTRICT_SLOT3ONLY, "Must execute on slot3", "", "") 112 | DEF_ATTRIB(RESTRICT_NOSLOT1, "No slot 1 instruction in parallel", "", "") 113 | DEF_ATTRIB(RESTRICT_PREFERSLOT0, "Try to encode into slot 0", "", "") 114 | 115 | DEF_ATTRIB(ICOP, "Instruction cache op", "", "") 116 | 117 | DEF_ATTRIB(HWLOOP0_END, "Ends HW loop0", "", "") 118 | DEF_ATTRIB(HWLOOP1_END, "Ends HW loop1", "", "") 119 | DEF_ATTRIB(DCZEROA, "dczeroa type", "", "") 120 | DEF_ATTRIB(ICTAGOP, "ictag op type", "", "") 121 | DEF_ATTRIB(ICFLUSHOP, "icflush op type", "", "") 122 | DEF_ATTRIB(DCFLUSHOP, "dcflush op type", "", "") 123 | DEF_ATTRIB(DCTAGOP, "dctag op type", "", "") 124 | DEF_ATTRIB(L2FLUSHOP, "l2flush op type", "", "") 125 | DEF_ATTRIB(L2TAGOP, "l2tag op type", "", "") 126 | DEF_ATTRIB(DCFETCH, "dcfetch type", "", "") 127 | 128 | DEF_ATTRIB(L2FETCH, "Instruction is l2fetch type", "", "") 129 | 130 | DEF_ATTRIB(ICINVA, "icinva", "", "") 131 | DEF_ATTRIB(DCCLEANINVA, "dccleaninva", "", "") 132 | 133 | DEF_ATTRIB(BN_RETURN, "Return from function", "", "") 134 | DEF_ATTRIB(BN_SYSTEM, "System call", "", "") 135 | DEF_ATTRIB(BN_COND_J, "Conditional jump", "", "") 136 | 137 | /* Keep this as the last attribute: */ 138 | DEF_ATTRIB(ZZ_LASTATTRIB, "Last attribute in the file", "", "") 139 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/bitmap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) 8 | 9 | #define BITS_PER_BYTE 8 10 | #define BITS_PER_LONG (sizeof(unsigned long) * BITS_PER_BYTE) 11 | 12 | #define BIT(nr) (1UL << (nr)) 13 | #define BIT_ULL(nr) (1ULL << (nr)) 14 | #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) 15 | #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) 16 | 17 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 18 | 19 | #define DECLARE_BITMAP(name, bits) unsigned long name[BITS_TO_LONGS(bits)] 20 | 21 | /** 22 | * set_bit - Set a bit in memory 23 | * @nr: the bit to set 24 | * @addr: the address to start counting from 25 | */ 26 | static inline void set_bit(long nr, unsigned long *addr) { 27 | unsigned long mask = BIT_MASK(nr); 28 | unsigned long *p = addr + BIT_WORD(nr); 29 | 30 | *p |= mask; 31 | } 32 | 33 | /** 34 | * test_bit - Determine whether a bit is set 35 | * @nr: bit number to test 36 | * @addr: Address to start counting from 37 | */ 38 | static inline int test_bit(long nr, const unsigned long *addr) { 39 | return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG - 1))); 40 | } 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/bitops.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | /** 8 | * extract32: 9 | * @value: the value to extract the bit field from 10 | * @start: the lowest bit in the bit field (numbered from 0) 11 | * @length: the length of the bit field 12 | * 13 | * Extract from the 32 bit input @value the bit field specified by the 14 | * @start and @length parameters, and return it. The bit field must 15 | * lie entirely within the 32 bit word. It is valid to request that 16 | * all 32 bits are returned (ie @length 32 and @start 0). 17 | * 18 | * Returns: the value of the bit field extracted from the input value. 19 | */ 20 | static inline uint32_t extract32(uint32_t value, int start, int length) { 21 | return (value >> start) & (~0U >> (32 - length)); 22 | } 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/cpu_bits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "third_party/qemu-hexagon/bitops.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #define HEX_EXCP_FETCH_NO_UPAGE 0x012 29 | #define HEX_EXCP_INVALID_PACKET 0x015 30 | #define HEX_EXCP_INVALID_OPCODE 0x015 31 | #define HEX_EXCP_PRIV_NO_UREAD 0x024 32 | #define HEX_EXCP_PRIV_NO_UWRITE 0x025 33 | 34 | #define HEX_EXCP_TRAP0 0x172 35 | #define HEX_EXCP_TRAP1 0x173 36 | 37 | #define PACKET_WORDS_MAX 4 38 | 39 | static inline uint32_t parse_bits(uint32_t encoding) { 40 | /* The parse bits are [15:14] */ 41 | return extract32(encoding, 14, 2); 42 | } 43 | 44 | static inline uint32_t iclass_bits(uint32_t encoding) { 45 | /* The instruction class is encoded in bits [31:28] */ 46 | uint32_t iclass = extract32(encoding, 28, 4); 47 | /* If parse bits are zero, this is a duplex */ 48 | if (parse_bits(encoding) == 0) { 49 | iclass += 16; 50 | } 51 | return iclass; 52 | } 53 | 54 | static inline int is_packet_end(uint32_t endocing) { 55 | uint32_t bits = parse_bits(endocing); 56 | return ((bits == 0x3) || (bits == 0x0)); 57 | } 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/decode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "third_party/qemu-hexagon/insn.h" 21 | #include "third_party/qemu-hexagon/opcodes.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | extern void decode_init(void); 28 | 29 | extern void decode_send_insn_to(Packet *packet, int start, int newloc); 30 | 31 | extern int decode_packet_safe(int max_words, const uint32_t *words, Packet *pkt, 32 | bool disas_only); 33 | 34 | extern void decode_remove_extenders(Packet *packet); 35 | extern void decode_shuffle_for_execution(Packet *packet); 36 | extern void decode_split_cmpjump(Packet *pkt); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/decode_ext_mmvec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "third_party/qemu-hexagon/iclass.h" 4 | #include "third_party/qemu-hexagon/insn.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern void mmvec_ext_decode_checks(Packet *pkt); 11 | extern SlotMask mmvec_ext_decode_find_iclass_slots(int opcode); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/gen_dectree_import.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * This program generates the encodings file that is processed by 20 | * the dectree.py script to produce the decoding tree. We use the C 21 | * preprocessor to manipulate the files imported from the Hexagon 22 | * architecture library. 23 | */ 24 | #include "third_party/qemu-hexagon/opcodes.h" 25 | 26 | #define STRINGIZE(X) #X 27 | 28 | const char *const opcode_names[] = { 29 | #define OPCODE(IID) STRINGIZE(IID) 30 | #include "opcodes_def_generated.h" 31 | NULL 32 | #undef OPCODE 33 | }; 34 | 35 | /* 36 | * Process the instruction definitions 37 | * Scalar core instructions have the following form 38 | * Q6INSN(A2_add,"Rd32=add(Rs32,Rt32)",ATTRIBS(), 39 | * "Add 32-bit registers", 40 | * { RdV=RsV+RtV;}) 41 | * HVX instructions have the following form 42 | * EXTINSN(V6_vinsertwr, "Vx32.w=vinsert(Rt32)", 43 | * ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VX,A_CVI_LATE), 44 | * "Insert Word Scalar into Vector", 45 | * VxV.uw[0] = RtV;) 46 | */ 47 | const char *const opcode_syntax[XX_LAST_OPCODE] = { 48 | #define Q6INSN(TAG, BEH, ATTRIBS, DESCR, SEM) [TAG] = BEH, 49 | #define EXTINSN(TAG, BEH, ATTRIBS, DESCR, SEM) [TAG] = BEH, 50 | #include "third_party/qemu-hexagon/imported/allidefs.def" 51 | #undef Q6INSN 52 | #undef EXTINSN 53 | }; 54 | 55 | const char *const opcode_rregs[] = { 56 | #define REGINFO(TAG, REGINFO, RREGS, WREGS) RREGS, 57 | #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ 58 | #include "op_regs_generated.h" 59 | NULL 60 | #undef REGINFO 61 | #undef IMMINFO 62 | }; 63 | 64 | const char *const opcode_wregs[] = { 65 | #define REGINFO(TAG, REGINFO, RREGS, WREGS) WREGS, 66 | #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ 67 | #include "op_regs_generated.h" 68 | NULL 69 | #undef REGINFO 70 | #undef IMMINFO 71 | }; 72 | 73 | const OpcodeEncoding opcode_encodings[] = { 74 | #define DEF_ENC32(TAG, ENCSTR) [TAG] = {.encoding = ENCSTR}, 75 | #define DEF_ENC_SUBINSN(TAG, CLASS, ENCSTR) \ 76 | [TAG] = {.encoding = ENCSTR, .enc_class = CLASS}, 77 | #define DEF_EXT_ENC(TAG, CLASS, ENCSTR) \ 78 | [TAG] = {.encoding = ENCSTR, .enc_class = CLASS}, 79 | #include "third_party/qemu-hexagon/imported/encode.def" 80 | #undef DEF_ENC32 81 | #undef DEF_ENC_SUBINSN 82 | #undef DEF_EXT_ENC 83 | }; 84 | 85 | static const char *const opcode_enc_class_names[XX_LAST_ENC_CLASS] = { 86 | "NORMAL", "16BIT", "SUBINSN_A", "SUBINSN_L1", "SUBINSN_L2", 87 | "SUBINSN_S1", "SUBINSN_S2", "EXT_noext", "EXT_mmvec", 88 | }; 89 | 90 | static const char *get_opcode_enc(int opcode) { 91 | const char *tmp = opcode_encodings[opcode].encoding; 92 | if (tmp == NULL) { 93 | tmp = "MISSING ENCODING"; 94 | } 95 | return tmp; 96 | } 97 | 98 | static const char *get_opcode_enc_class(int opcode) { 99 | const char *tmp = opcode_encodings[opcode].encoding; 100 | if (tmp == NULL) { 101 | const char *test = "V6_"; /* HVX */ 102 | char *name = (char *)opcode_names[opcode]; 103 | if (strncmp(name, test, strlen(test)) == 0) { 104 | return "EXT_mmvec"; 105 | } 106 | } 107 | return opcode_enc_class_names[opcode_encodings[opcode].enc_class]; 108 | } 109 | 110 | static void gen_iset_table(FILE *out) { 111 | int i; 112 | 113 | fprintf(out, "iset = {\n"); 114 | for (i = 0; i < XX_LAST_OPCODE; i++) { 115 | fprintf(out, "\t\'%s\' : {\n", opcode_names[i]); 116 | fprintf(out, "\t\t\'tag\' : \'%s\',\n", opcode_names[i]); 117 | fprintf(out, "\t\t\'syntax\' : \'%s\',\n", opcode_syntax[i]); 118 | fprintf(out, "\t\t\'rregs\' : \'%s\',\n", opcode_rregs[i]); 119 | fprintf(out, "\t\t\'wregs\' : \'%s\',\n", opcode_wregs[i]); 120 | fprintf(out, "\t\t\'enc\' : \'%s\',\n", get_opcode_enc(i)); 121 | fprintf(out, "\t\t\'enc_class\' : \'%s\',\n", get_opcode_enc_class(i)); 122 | fprintf(out, "\t},\n"); 123 | } 124 | fprintf(out, "};\n\n"); 125 | } 126 | 127 | static void gen_tags_list(FILE *out) { 128 | int i; 129 | 130 | fprintf(out, "tags = [\n"); 131 | for (i = 0; i < XX_LAST_OPCODE; i++) { 132 | fprintf(out, "\t\'%s\',\n", opcode_names[i]); 133 | } 134 | fprintf(out, "];\n\n"); 135 | } 136 | 137 | static void gen_enc_ext_spaces_table(FILE *out) { 138 | fprintf(out, "enc_ext_spaces = {\n"); 139 | #define DEF_EXT_SPACE(SPACEID, ENCSTR) \ 140 | fprintf(out, "\t\'%s\' : \'%s\',\n", #SPACEID, ENCSTR); 141 | #include "third_party/qemu-hexagon/imported/encode.def" 142 | #undef DEF_EXT_SPACE 143 | fprintf(out, "};\n\n"); 144 | } 145 | 146 | static void gen_subinsn_groupings_table(FILE *out) { 147 | fprintf(out, "subinsn_groupings = {\n"); 148 | #define DEF_PACKED32(TAG, TYPEA, TYPEB, ENCSTR) \ 149 | do { \ 150 | fprintf(out, "\t\'%s\' : {\n", #TAG); \ 151 | fprintf(out, "\t\t\'name\' : \'%s\',\n", #TAG); \ 152 | fprintf(out, "\t\t\'class_a\' : \'%s\',\n", #TYPEA); \ 153 | fprintf(out, "\t\t\'class_b\' : \'%s\',\n", #TYPEB); \ 154 | fprintf(out, "\t\t\'enc\' : \'%s\',\n", ENCSTR); \ 155 | fprintf(out, "\t},\n"); \ 156 | } while (0); 157 | #include "third_party/qemu-hexagon/imported/encode.def" 158 | #undef DEF_PACKED32 159 | fprintf(out, "};\n\n"); 160 | } 161 | 162 | int main(int argc, char *argv[]) { 163 | FILE *outfile; 164 | 165 | if (argc != 2) { 166 | fprintf(stderr, "Usage: gen_dectree_import ouptputfile\n"); 167 | return 1; 168 | } 169 | outfile = fopen(argv[1], "w"); 170 | if (outfile == NULL) { 171 | fprintf(stderr, "Cannot open %s for writing\n", argv[1]); 172 | return 1; 173 | } 174 | 175 | gen_iset_table(outfile); 176 | gen_tags_list(outfile); 177 | gen_enc_ext_spaces_table(outfile); 178 | gen_subinsn_groupings_table(outfile); 179 | 180 | fclose(outfile); 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/gen_op_attribs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ## 4 | ## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 5 | ## 6 | ## This program is free software; you can redistribute it and/or modify 7 | ## it under the terms of the GNU General Public License as published by 8 | ## the Free Software Foundation; either version 2 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This program is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU General Public License 17 | ## along with this program; if not, see . 18 | ## 19 | 20 | import sys 21 | import re 22 | import string 23 | from io import StringIO 24 | 25 | from hex_common import * 26 | 27 | 28 | def main(): 29 | read_semantics_file(sys.argv[1]) 30 | read_attribs_file(sys.argv[2]) 31 | calculate_attribs() 32 | 33 | ## 34 | ## Generate the op_attribs_generated.h file 35 | ## Lists all the attributes associated with each instruction 36 | ## 37 | f = StringIO() 38 | for tag in tags: 39 | f.write('OP_ATTRIB(%s,ATTRIBS(%s))\n' % \ 40 | (tag, ','.join(sorted(attribdict[tag])))) 41 | realf = open(sys.argv[3], 'wt') 42 | realf.write(f.getvalue()) 43 | realf.close() 44 | f.close() 45 | 46 | 47 | if __name__ == "__main__": 48 | main() 49 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/gen_op_regs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ## 4 | ## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 5 | ## 6 | ## This program is free software; you can redistribute it and/or modify 7 | ## it under the terms of the GNU General Public License as published by 8 | ## the Free Software Foundation; either version 2 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This program is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU General Public License 17 | ## along with this program; if not, see . 18 | ## 19 | 20 | import sys 21 | import re 22 | import string 23 | from io import StringIO 24 | 25 | from hex_common import * 26 | 27 | 28 | ## 29 | ## Generate the op_regs_generated.h file 30 | ## Lists the register and immediate operands for each instruction 31 | ## 32 | def calculate_regid_reg(tag): 33 | 34 | def letter_inc(x): 35 | return chr(ord(x) + 1) 36 | 37 | ordered_implregs = ['SP', 'FP', 'LR'] 38 | srcdst_lett = 'X' 39 | src_lett = 'S' 40 | dst_lett = 'D' 41 | retstr = "" 42 | mapdict = {} 43 | for reg in ordered_implregs: 44 | reg_rd = 0 45 | reg_wr = 0 46 | if ('A_IMPLICIT_WRITES_' + reg) in attribdict[tag]: 47 | reg_wr = 1 48 | if reg_rd and reg_wr: 49 | retstr += srcdst_lett 50 | mapdict[srcdst_lett] = reg 51 | srcdst_lett = letter_inc(srcdst_lett) 52 | elif reg_rd: 53 | retstr += src_lett 54 | mapdict[src_lett] = reg 55 | src_lett = letter_inc(src_lett) 56 | elif reg_wr: 57 | retstr += dst_lett 58 | mapdict[dst_lett] = reg 59 | dst_lett = letter_inc(dst_lett) 60 | return retstr, mapdict 61 | 62 | 63 | def calculate_regid_letters(tag): 64 | retstr, mapdict = calculate_regid_reg(tag) 65 | return retstr 66 | 67 | 68 | def strip_reg_prefix(x): 69 | y = x.replace('UREG.', '') 70 | y = y.replace('MREG.', '') 71 | return y.replace('GREG.', '') 72 | 73 | 74 | def main(): 75 | read_semantics_file(sys.argv[1]) 76 | read_attribs_file(sys.argv[2]) 77 | tagregs = get_tagregs() 78 | tagimms = get_tagimms() 79 | 80 | f = StringIO() 81 | 82 | for tag in tags: 83 | regs = tagregs[tag] 84 | rregs = [] 85 | wregs = [] 86 | regids = "" 87 | for regtype, regid, toss, numregs in regs: 88 | if is_read(regid): 89 | if regid[0] not in regids: 90 | regids += regid[0] 91 | rregs.append(regtype + regid + numregs) 92 | if is_written(regid): 93 | wregs.append(regtype + regid + numregs) 94 | if regid[0] not in regids: 95 | regids += regid[0] 96 | for attrib in attribdict[tag]: 97 | if attribinfo[attrib]['rreg']: 98 | rregs.append(strip_reg_prefix(attribinfo[attrib]['rreg'])) 99 | if attribinfo[attrib]['wreg']: 100 | wregs.append(strip_reg_prefix(attribinfo[attrib]['wreg'])) 101 | regids += calculate_regid_letters(tag) 102 | f.write('REGINFO(%s,"%s",\t/*RD:*/\t"%s",\t/*WR:*/\t"%s")\n' % \ 103 | (tag,regids,",".join(rregs),",".join(wregs))) 104 | 105 | for tag in tags: 106 | imms = tagimms[tag] 107 | f.write('IMMINFO(%s' % tag) 108 | if not imms: 109 | f.write(''','u',0,0,'U',0,0''') 110 | for sign, size, shamt in imms: 111 | if sign == 'r': 112 | sign = 's' 113 | if not shamt: 114 | shamt = "0" 115 | f.write(''','%s',%s,%s''' % (sign, size, shamt)) 116 | if len(imms) == 1: 117 | if sign.isupper(): 118 | myu = 'u' 119 | else: 120 | myu = 'U' 121 | f.write(''','%s',0,0''' % myu) 122 | f.write(')\n') 123 | 124 | realf = open(sys.argv[3], 'w') 125 | realf.write(f.getvalue()) 126 | realf.close() 127 | f.close() 128 | 129 | 130 | if __name__ == "__main__": 131 | main() 132 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/gen_opcodes_def.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ## 4 | ## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 5 | ## 6 | ## This program is free software; you can redistribute it and/or modify 7 | ## it under the terms of the GNU General Public License as published by 8 | ## the Free Software Foundation; either version 2 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This program is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU General Public License 17 | ## along with this program; if not, see . 18 | ## 19 | 20 | import sys 21 | import re 22 | import string 23 | from io import StringIO 24 | 25 | from hex_common import * 26 | 27 | 28 | def main(): 29 | read_semantics_file(sys.argv[1]) 30 | 31 | ## 32 | ## Generate the opcodes_def_generated.h file 33 | ## Gives a list of all the opcodes 34 | ## 35 | f = StringIO() 36 | for tag in tags: 37 | f.write("OPCODE(%s),\n" % (tag)) 38 | realf = open(sys.argv[3], 'wt') 39 | realf.write(f.getvalue()) 40 | realf.close() 41 | f.close() 42 | 43 | 44 | if __name__ == "__main__": 45 | main() 46 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/gen_semantics.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * This program generates the semantics file that is processed by 20 | * the do_qemu.py script. We use the C preporcessor to manipulate the 21 | * files imported from the Hexagon architecture library. 22 | */ 23 | 24 | #include 25 | #define STRINGIZE(X) #X 26 | 27 | int main(int argc, char *argv[]) { 28 | FILE *outfile; 29 | 30 | if (argc != 2) { 31 | fprintf(stderr, "Usage: gen_semantics ouptputfile\n"); 32 | return 1; 33 | } 34 | outfile = fopen(argv[1], "w"); 35 | if (outfile == NULL) { 36 | fprintf(stderr, "Cannot open %s for writing\n", argv[1]); 37 | return 1; 38 | } 39 | 40 | /* 41 | * Process the instruction definitions 42 | * Scalar core instructions have the following form 43 | * Q6INSN(A2_add,"Rd32=add(Rs32,Rt32)",ATTRIBS(), 44 | * "Add 32-bit registers", 45 | * { RdV=RsV+RtV;}) 46 | * HVX instructions have the following form 47 | * EXTINSN(V6_vinsertwr, "Vx32.w=vinsert(Rt32)", 48 | * ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VX), 49 | * "Insert Word Scalar into Vector", 50 | * VxV.uw[0] = RtV;) 51 | */ 52 | #define Q6INSN(TAG, BEH, ATTRIBS, DESCR, SEM) \ 53 | do { \ 54 | fprintf(outfile, \ 55 | "SEMANTICS( \\\n" \ 56 | " \"%s\", \\\n" \ 57 | " %s, \\\n" \ 58 | " \"\"\"%s\"\"\" \\\n" \ 59 | ")\n", \ 60 | #TAG, STRINGIZE(BEH), STRINGIZE(SEM)); \ 61 | fprintf(outfile, \ 62 | "ATTRIBUTES( \\\n" \ 63 | " \"%s\", \\\n" \ 64 | " \"%s\" \\\n" \ 65 | ")\n", \ 66 | #TAG, STRINGIZE(ATTRIBS)); \ 67 | } while (0); 68 | #define EXTINSN(TAG, BEH, ATTRIBS, DESCR, SEM) \ 69 | do { \ 70 | fprintf(outfile, \ 71 | "SEMANTICS( \\\n" \ 72 | " \"%s\", \\\n" \ 73 | " %s, \\\n" \ 74 | " \"\"\"%s\"\"\" \\\n" \ 75 | ")\n", \ 76 | #TAG, STRINGIZE(BEH), STRINGIZE(SEM)); \ 77 | fprintf(outfile, \ 78 | "ATTRIBUTES( \\\n" \ 79 | " \"%s\", \\\n" \ 80 | " \"%s\" \\\n" \ 81 | ")\n", \ 82 | #TAG, STRINGIZE(ATTRIBS)); \ 83 | } while (0); 84 | #include "third_party/qemu-hexagon/imported/allidefs.def" 85 | #undef Q6INSN 86 | #undef EXTINSN 87 | 88 | /* 89 | * Process the macro definitions 90 | * Macros definitions have the following form 91 | * DEF_MACRO( 92 | * fLSBNEW0, 93 | * predlog_read(thread,0), 94 | * () 95 | * ) 96 | * The important part here is the attributes. Whenever an instruction 97 | * invokes a macro, we add the macro's attributes to the instruction. 98 | */ 99 | #define DEF_MACRO(MNAME, BEH, ATTRS) \ 100 | fprintf(outfile, \ 101 | "MACROATTRIB( \\\n" \ 102 | " \"%s\", \\\n" \ 103 | " \"\"\"%s\"\"\", \\\n" \ 104 | " \"%s\" \\\n" \ 105 | ")\n", \ 106 | #MNAME, STRINGIZE(BEH), STRINGIZE(ATTRS)); 107 | #include "third_party/qemu-hexagon/imported/macros.def" 108 | #undef DEF_MACRO 109 | 110 | /* 111 | * Process the macros for HVX 112 | */ 113 | #define DEF_MACRO(MNAME, BEH, ATTRS) \ 114 | fprintf(outfile, \ 115 | "MACROATTRIB( \\\n" \ 116 | " \"%s\", \\\n" \ 117 | " \"\"\"%s\"\"\", \\\n" \ 118 | " \"%s\" \\\n" \ 119 | ")\n", \ 120 | #MNAME, STRINGIZE(BEH), STRINGIZE(ATTRS)); 121 | #include "third_party/qemu-hexagon/imported/allext_macros.def" 122 | #undef DEF_MACRO 123 | 124 | fclose(outfile); 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/gen_shortcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ## 4 | ## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 5 | ## 6 | ## This program is free software; you can redistribute it and/or modify 7 | ## it under the terms of the GNU General Public License as published by 8 | ## the Free Software Foundation; either version 2 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This program is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU General Public License 17 | ## along with this program; if not, see . 18 | ## 19 | 20 | import sys 21 | import re 22 | import string 23 | from io import StringIO 24 | 25 | from hex_common import * 26 | 27 | 28 | def gen_shortcode(f, tag): 29 | f.write('DEF_SHORTCODE(%s, %s)\n' % (tag, semdict[tag])) 30 | 31 | 32 | def main(): 33 | read_semantics_file(sys.argv[1]) 34 | read_attribs_file(sys.argv[2]) 35 | calculate_attribs() 36 | tagregs = get_tagregs() 37 | tagimms = get_tagimms() 38 | 39 | ## 40 | ## Generate the shortcode_generated.h file 41 | ## 42 | f = StringIO() 43 | 44 | f.write("#ifndef DEF_SHORTCODE\n") 45 | f.write("#define DEF_SHORTCODE(TAG,SHORTCODE) /* Nothing */\n") 46 | f.write("#endif\n") 47 | 48 | for tag in tags: 49 | ## Skip the priv instructions 50 | if ("A_PRIV" in attribdict[tag]): 51 | continue 52 | ## Skip the guest instructions 53 | if ("A_GUEST" in attribdict[tag]): 54 | continue 55 | ## Skip the diag instructions 56 | if (tag == "Y6_diag"): 57 | continue 58 | if (tag == "Y6_diag0"): 59 | continue 60 | if (tag == "Y6_diag1"): 61 | continue 62 | 63 | gen_shortcode(f, tag) 64 | 65 | f.write("#undef DEF_SHORTCODE\n") 66 | 67 | realf = open(sys.argv[3], 'w') 68 | realf.write(f.getvalue()) 69 | realf.close() 70 | f.close() 71 | 72 | 73 | if __name__ == "__main__": 74 | main() 75 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/hex_common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ## 4 | ## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 5 | ## 6 | ## This program is free software; you can redistribute it and/or modify 7 | ## it under the terms of the GNU General Public License as published by 8 | ## the Free Software Foundation; either version 2 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This program is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU General Public License 17 | ## along with this program; if not, see . 18 | ## 19 | 20 | import sys 21 | import re 22 | import string 23 | from io import StringIO 24 | 25 | behdict = {} # tag ->behavior 26 | semdict = {} # tag -> semantics 27 | attribdict = {} # tag -> attributes 28 | macros = {} # macro -> macro information... 29 | attribinfo = {} # Register information and misc 30 | tags = [] # list of all tags 31 | 32 | 33 | # We should do this as a hash for performance, 34 | # but to keep order let's keep it as a list. 35 | def uniquify(seq): 36 | seen = set() 37 | seen_add = seen.add 38 | return [x for x in seq if x not in seen and not seen_add(x)] 39 | 40 | 41 | regre = re.compile( 42 | r"((?" % l) 62 | macro.attribs |= expand_macro_attribs(macros[submacro], allmac_re) 63 | finished_macros.add(macro.key) 64 | return macro.attribs 65 | 66 | 67 | immextre = re.compile(r'f(MUST_)?IMMEXT[(]([UuSsRr])') 68 | 69 | 70 | def calculate_attribs(): 71 | # Recurse down macros, find attributes from sub-macros 72 | macroValues = list(macros.values()) 73 | allmacros_restr = "|".join(set([m.re.pattern for m in macroValues])) 74 | allmacros_re = re.compile(allmacros_restr) 75 | for macro in macroValues: 76 | expand_macro_attribs(macro, allmacros_re) 77 | # Append attributes to all instructions 78 | for tag in tags: 79 | for macname in allmacros_re.findall(semdict[tag]): 80 | if not macname: 81 | continue 82 | macro = macros[macname] 83 | attribdict[tag] |= set(macro.attribs) 84 | 85 | 86 | def SEMANTICS(tag, beh, sem): 87 | #print tag,beh,sem 88 | behdict[tag] = beh 89 | semdict[tag] = sem 90 | attribdict[tag] = set() 91 | tags.append(tag) # dicts have no order, this is for order 92 | 93 | 94 | def ATTRIBUTES(tag, attribstring): 95 | attribstring = \ 96 | attribstring.replace("ATTRIBS","").replace("(","").replace(")","") 97 | if not attribstring: 98 | return 99 | attribs = attribstring.split(",") 100 | for attrib in attribs: 101 | attribdict[tag].add(attrib.strip()) 102 | 103 | 104 | class Macro(object): 105 | __slots__ = ['key', 'name', 'beh', 'attribs', 're'] 106 | 107 | def __init__(self, name, beh, attribs): 108 | self.key = name 109 | self.name = name 110 | self.beh = beh 111 | self.attribs = set(attribs) 112 | self.re = re.compile("\\b" + name + "\\b") 113 | 114 | 115 | def MACROATTRIB(macname, beh, attribstring): 116 | attribstring = attribstring.replace("(", "").replace(")", "") 117 | if attribstring: 118 | attribs = attribstring.split(",") 119 | else: 120 | attribs = [] 121 | macros[macname] = Macro(macname, beh, attribs) 122 | 123 | 124 | def compute_tag_regs(tag): 125 | return uniquify(regre.findall(behdict[tag])) 126 | 127 | 128 | def compute_tag_immediates(tag): 129 | return uniquify(immre.findall(behdict[tag])) 130 | 131 | 132 | ## 133 | ## tagregs is the main data structure we'll use 134 | ## tagregs[tag] will contain the registers used by an instruction 135 | ## Within each entry, we'll use the regtype and regid fields 136 | ## regtype can be one of the following 137 | ## C control register 138 | ## N new register value 139 | ## P predicate register 140 | ## R GPR register 141 | ## M modifier register 142 | ## Q HVX predicate vector 143 | ## V HVX vector register 144 | ## O HVX new vector register 145 | ## regid can be one of the following 146 | ## d, e destination register 147 | ## dd destination register pair 148 | ## s, t, u, v, w source register 149 | ## ss, tt, uu, vv source register pair 150 | ## x, y read-write register 151 | ## xx, yy read-write register pair 152 | ## 153 | def get_tagregs(): 154 | return dict(zip(tags, list(map(compute_tag_regs, tags)))) 155 | 156 | 157 | def get_tagimms(): 158 | return dict(zip(tags, list(map(compute_tag_immediates, tags)))) 159 | 160 | 161 | def is_pair(regid): 162 | return len(regid) == 2 163 | 164 | 165 | def is_single(regid): 166 | return len(regid) == 1 167 | 168 | 169 | def is_written(regid): 170 | return regid[0] in "dexy" 171 | 172 | 173 | def is_writeonly(regid): 174 | return regid[0] in "de" 175 | 176 | 177 | def is_read(regid): 178 | return regid[0] in "stuvwxy" 179 | 180 | 181 | def is_readwrite(regid): 182 | return regid[0] in "xy" 183 | 184 | 185 | def is_scalar_reg(regtype): 186 | return regtype in "RPC" 187 | 188 | 189 | def is_hvx_reg(regtype): 190 | return regtype in "VQ" 191 | 192 | 193 | def is_old_val(regtype, regid, tag): 194 | return regtype + regid + 'V' in semdict[tag] 195 | 196 | 197 | def is_new_val(regtype, regid, tag): 198 | return regtype + regid + 'N' in semdict[tag] 199 | 200 | 201 | def need_slot(tag): 202 | if ('A_CONDEXEC' in attribdict[tag] or 'A_STORE' in attribdict[tag] or 203 | 'A_CVI' in attribdict[tag]): 204 | return 1 205 | else: 206 | return 0 207 | 208 | 209 | def need_part1(tag): 210 | return re.compile(r"fPART1").search(semdict[tag]) 211 | 212 | 213 | def need_ea(tag): 214 | return re.compile(r"\bEA\b").search(semdict[tag]) 215 | 216 | 217 | def imm_name(immlett): 218 | return "%siV" % immlett 219 | 220 | 221 | def read_semantics_file_obj(f): 222 | eval_line = "" 223 | for line in f.readlines(): 224 | if not line.startswith("#"): 225 | eval_line += line 226 | if line.endswith("\\\n"): 227 | eval_line.rstrip("\\\n") 228 | else: 229 | eval(eval_line.strip()) 230 | eval_line = "" 231 | 232 | 233 | def read_semantics_file(name): 234 | with open(name, 'rt') as f: 235 | read_semantics_file_obj(f) 236 | 237 | 238 | def read_attribs_file_obj(f): 239 | attribre = re.compile(r'DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), ' + 240 | r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)') 241 | for line in f.readlines(): 242 | if not attribre.match(line): 243 | continue 244 | (attrib_base, descr, rreg, wreg) = attribre.findall(line)[0] 245 | attrib_base = 'A_' + attrib_base 246 | attribinfo[attrib_base] = {'rreg': rreg, 'wreg': wreg, 'descr': descr} 247 | 248 | 249 | def read_attribs_file(name): 250 | with open(name, 'rt') as f: 251 | read_attribs_file_obj(f) 252 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/iclass.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #include "third_party/qemu-hexagon/iclass.h" 19 | 20 | static const SlotMask iclass_info[] = { 21 | 22 | #define DEF_PP_ICLASS32(TYPE, SLOTS, UNITS) \ 23 | [ICLASS_FROM_TYPE(TYPE)] = SLOTS_##SLOTS, 24 | #define DEF_EE_ICLASS32(TYPE, SLOTS, UNITS) \ 25 | [ICLASS_FROM_TYPE(TYPE)] = SLOTS_##SLOTS, 26 | #include "third_party/qemu-hexagon/imported/iclass.def" 27 | #undef DEF_PP_ICLASS32 28 | #undef DEF_EE_ICLASS32 29 | }; 30 | 31 | SlotMask find_iclass_slots(Opcode opcode, int itype) { 32 | /* There are some exceptions to what the iclass dictates */ 33 | if (GET_ATTRIB(opcode, A_ICOP)) { 34 | return SLOTS_2; 35 | } else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT0ONLY)) { 36 | return SLOTS_0; 37 | } else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT1ONLY)) { 38 | return SLOTS_1; 39 | } else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT2ONLY)) { 40 | return SLOTS_2; 41 | } else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT3ONLY)) { 42 | return SLOTS_3; 43 | } else if (GET_ATTRIB(opcode, A_COF) && GET_ATTRIB(opcode, A_INDIRECT) && 44 | !GET_ATTRIB(opcode, A_MEMLIKE) && 45 | !GET_ATTRIB(opcode, A_MEMLIKE_PACKET_RULES)) { 46 | return SLOTS_2; 47 | } else if (GET_ATTRIB(opcode, A_RESTRICT_NOSLOT1)) { 48 | return SLOTS_0; 49 | } else if ((opcode == J2_trap0) || (opcode == J2_trap1) || 50 | (opcode == Y2_isync) || (opcode == J2_rte) || 51 | (opcode == J2_pause) || (opcode == J4_hintjumpr)) { 52 | return SLOTS_2; 53 | } else if ((itype == ICLASS_V2LDST) && (GET_ATTRIB(opcode, A_STORE))) { 54 | return SLOTS_01; 55 | } else if ((itype == ICLASS_V2LDST) && (!GET_ATTRIB(opcode, A_STORE))) { 56 | return SLOTS_01; 57 | } else if (GET_ATTRIB(opcode, A_CRSLOT23)) { 58 | return SLOTS_23; 59 | } else if (GET_ATTRIB(opcode, A_RESTRICT_PREFERSLOT0)) { 60 | return SLOTS_0; 61 | } else if (GET_ATTRIB(opcode, A_SUBINSN)) { 62 | return SLOTS_01; 63 | } else if (GET_ATTRIB(opcode, A_CALL)) { 64 | return SLOTS_23; 65 | } else if ((opcode == J4_jumpseti) || (opcode == J4_jumpsetr)) { 66 | return SLOTS_23; 67 | } else if (GET_ATTRIB(opcode, A_EXTENSION) && GET_ATTRIB(opcode, A_CVI)) { 68 | /* CVI EXTENSIONS */ 69 | if (GET_ATTRIB(opcode, A_CVI_VM)) { 70 | return SLOTS_01; 71 | } else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT2ONLY)) { 72 | return SLOTS_2; 73 | } else if (GET_ATTRIB(opcode, A_CVI_SLOT23)) { 74 | return SLOTS_23; 75 | } else if (GET_ATTRIB(opcode, A_CVI_VX)) { 76 | return SLOTS_23; 77 | } else if (GET_ATTRIB(opcode, A_CVI_VX_DV)) { 78 | return SLOTS_23; 79 | } else if (GET_ATTRIB(opcode, A_CVI_VS_VX)) { 80 | return SLOTS_23; 81 | } else if (GET_ATTRIB(opcode, A_MEMLIKE)) { 82 | return SLOTS_01; 83 | } else { 84 | return SLOTS_0123; 85 | } 86 | } else { 87 | return iclass_info[itype]; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/iclass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "third_party/qemu-hexagon/opcodes.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #define ICLASS_FROM_TYPE(TYPE) ICLASS_##TYPE 27 | 28 | enum { 29 | 30 | #define DEF_PP_ICLASS32(TYPE, SLOTS, UNITS) ICLASS_FROM_TYPE(TYPE), 31 | #define DEF_EE_ICLASS32(TYPE, SLOTS, UNITS) ICLASS_FROM_TYPE(TYPE), 32 | #include "third_party/qemu-hexagon/imported/iclass.def" 33 | #undef DEF_PP_ICLASS32 34 | #undef DEF_EE_ICLASS32 35 | 36 | ICLASS_FROM_TYPE(COPROC_VX), 37 | ICLASS_FROM_TYPE(COPROC_VMEM), 38 | NUM_ICLASSES 39 | }; 40 | 41 | typedef enum { 42 | SLOTS_0 = (1 << 0), 43 | SLOTS_1 = (1 << 1), 44 | SLOTS_2 = (1 << 2), 45 | SLOTS_3 = (1 << 3), 46 | SLOTS_01 = SLOTS_0 | SLOTS_1, 47 | SLOTS_23 = SLOTS_2 | SLOTS_3, 48 | SLOTS_0123 = SLOTS_0 | SLOTS_1 | SLOTS_2 | SLOTS_3, 49 | } SlotMask; 50 | 51 | extern SlotMask find_iclass_slots(Opcode opcode, int itype); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/imported/allext.idef: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * Top level file for all instruction set extensions 20 | */ 21 | #define EXTNAME mmvec 22 | #define EXTSTR "mmvec" 23 | #include "mmvec/ext.idef" 24 | #undef EXTNAME 25 | #undef EXTSTR 26 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/imported/allext_macros.def: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * Top level file for all instruction set extensions 20 | */ 21 | #define EXTNAME mmvec 22 | #define EXTSTR "mmvec" 23 | #include "mmvec/macros.def" 24 | #undef EXTNAME 25 | #undef EXTSTR 26 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/imported/allextenc.def: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #define EXTNAME mmvec 19 | #include "mmvec/encode_ext.def" 20 | #undef EXTNAME 21 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/imported/allidefs.def: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * Top level instruction definition file 20 | */ 21 | 22 | #include "branch.idef" 23 | #include "ldst.idef" 24 | #include "compare.idef" 25 | #include "mpy.idef" 26 | #include "alu.idef" 27 | #include "float.idef" 28 | #include "shift.idef" 29 | #include "system.idef" 30 | #include "subinsns.idef" 31 | #include "allext.idef" 32 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/imported/encode.def: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * This just includes all encoding files 20 | */ 21 | 22 | #ifndef DEF_FIELD32 23 | #define __SELF_DEF_FIELD32 24 | #define DEF_FIELD32(...) /* nothing */ 25 | #endif 26 | 27 | #ifndef DEF_CLASS32 28 | #define __SELF_DEF_CLASS32 29 | #define DEF_CLASS32(...) /* nothing */ 30 | #endif 31 | 32 | #ifndef DEF_ANTICLASS32 33 | #define __SELF_DEF_ANTICLASS32 34 | #define DEF_ANTICLASS32(...) /* nothing */ 35 | #endif 36 | 37 | #ifndef LEGACY_DEF_ENC32 38 | #define __SELF_DEF_LEGACY_DEF_ENC32 39 | #define LEGACY_DEF_ENC32(...) /* nothing */ 40 | #endif 41 | 42 | #ifndef DEF_FIELDROW_DESC32 43 | #define __SELF_DEF_FIELDROW_DESC32 44 | #define DEF_FIELDROW_DESC32(...) /* nothing */ 45 | #endif 46 | 47 | #ifndef DEF_ENC32 48 | #define __SELF_DEF_ENC32 49 | #define DEF_ENC32(...) /* nothing */ 50 | #endif 51 | 52 | #ifndef DEF_PACKED32 53 | #define __SELF_DEF_PACKED32 54 | #define DEF_PACKED32(...) /* nothing */ 55 | #endif 56 | 57 | #ifndef DEF_ENC_SUBINSN 58 | #define __SELF_DEF_ENC_SUBINSN 59 | #define DEF_ENC_SUBINSN(...) /* nothing */ 60 | #endif 61 | 62 | #ifndef DEF_EXT_ENC 63 | #define __SELF_DEF_EXT_ENC 64 | #define DEF_EXT_ENC(...) /* nothing */ 65 | #endif 66 | 67 | #ifndef DEF_EXT_SPACE 68 | #define __SELF_DEF_EXT_SPACE 69 | #define DEF_EXT_SPACE(...) /* nothing */ 70 | #endif 71 | 72 | #include "encode_pp.def" 73 | #include "encode_subinsn.def" 74 | #include "allextenc.def" 75 | 76 | #ifdef __SELF_DEF_FIELD32 77 | #undef __SELF_DEF_FIELD32 78 | #undef DEF_FIELD32 79 | #endif 80 | 81 | #ifdef __SELF_DEF_CLASS32 82 | #undef __SELF_DEF_CLASS32 83 | #undef DEF_CLASS32 84 | #endif 85 | 86 | #ifdef __SELF_DEF_ANTICLASS32 87 | #undef __SELF_DEF_ANTICLASS32 88 | #undef DEF_ANTICLASS32 89 | #endif 90 | 91 | #ifdef __SELF_DEF_LEGACY_DEF_ENC32 92 | #undef __SELF_DEF_LEGACY_DEF_ENC32 93 | #undef LEGACY_DEF_ENC32 94 | #endif 95 | 96 | #ifdef __SELF_DEF_FIELDROW_DESC32 97 | #undef __SELF_DEF_FIELDROW_DESC32 98 | #undef DEF_FIELDROW_DESC32 99 | #endif 100 | 101 | #ifdef __SELF_DEF_ENC32 102 | #undef __SELF_DEF_ENC32 103 | #undef DEF_ENC32 104 | #endif 105 | 106 | #ifdef __SELF_DEF_EXT_SPACE 107 | #undef __SELF_DEF_EXT_SPACE 108 | #undef DEF_EXT_SPACE 109 | #endif 110 | 111 | 112 | #ifdef __SELF_DEF_PACKED32 113 | #undef __SELF_DEF_PACKED32 114 | #undef DEF_PACKED32 115 | #endif 116 | 117 | #ifdef __SELF_DEF_ENC_SUBINSN 118 | #undef __SELF_DEF_ENC_SUBINSN 119 | #undef DEF_ENC_SUBINSN 120 | #endif 121 | 122 | #ifdef __SELF_DEF_EXT_ENC 123 | #undef __SELF_DEF_EXT_ENC 124 | #undef DEF_EXT_ENC 125 | #endif 126 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/imported/encode_subinsn.def: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | 19 | /* DEF_ENC_SUBINSN(TAG, CLASS, ENCSTR) */ 20 | 21 | 22 | 23 | 24 | /*********************/ 25 | /* Ld1-type subinsns */ 26 | /*********************/ 27 | DEF_ENC_SUBINSN(SL1_loadri_io, SUBINSN_L1, "0iiiissssdddd") 28 | DEF_ENC_SUBINSN(SL1_loadrub_io, SUBINSN_L1, "1iiiissssdddd") 29 | 30 | /*********************/ 31 | /* St1-type subinsns */ 32 | /*********************/ 33 | DEF_ENC_SUBINSN(SS1_storew_io, SUBINSN_S1, "0ii iisssstttt") 34 | DEF_ENC_SUBINSN(SS1_storeb_io, SUBINSN_S1, "1ii iisssstttt") 35 | 36 | 37 | /*********************/ 38 | /* Ld2-type subinsns */ 39 | /*********************/ 40 | DEF_ENC_SUBINSN(SL2_loadrh_io, SUBINSN_L2, "00i iissssdddd") 41 | DEF_ENC_SUBINSN(SL2_loadruh_io, SUBINSN_L2, "01i iissssdddd") 42 | DEF_ENC_SUBINSN(SL2_loadrb_io, SUBINSN_L2, "10i iissssdddd") 43 | DEF_ENC_SUBINSN(SL2_loadri_sp, SUBINSN_L2, "111 0iiiiidddd") 44 | DEF_ENC_SUBINSN(SL2_loadrd_sp, SUBINSN_L2, "111 10iiiiiddd") 45 | 46 | DEF_ENC_SUBINSN(SL2_deallocframe,SUBINSN_L2, "111 1100---0--") 47 | 48 | DEF_ENC_SUBINSN(SL2_return, SUBINSN_L2, "111 1101---0--") 49 | DEF_ENC_SUBINSN(SL2_return_t, SUBINSN_L2, "111 1101---100") 50 | DEF_ENC_SUBINSN(SL2_return_f, SUBINSN_L2, "111 1101---101") 51 | DEF_ENC_SUBINSN(SL2_return_tnew, SUBINSN_L2, "111 1101---110") 52 | DEF_ENC_SUBINSN(SL2_return_fnew, SUBINSN_L2, "111 1101---111") 53 | 54 | DEF_ENC_SUBINSN(SL2_jumpr31, SUBINSN_L2, "111 1111---0--") 55 | DEF_ENC_SUBINSN(SL2_jumpr31_t, SUBINSN_L2, "111 1111---100") 56 | DEF_ENC_SUBINSN(SL2_jumpr31_f, SUBINSN_L2, "111 1111---101") 57 | DEF_ENC_SUBINSN(SL2_jumpr31_tnew,SUBINSN_L2, "111 1111---110") 58 | DEF_ENC_SUBINSN(SL2_jumpr31_fnew,SUBINSN_L2, "111 1111---111") 59 | 60 | 61 | /*********************/ 62 | /* St2-type subinsns */ 63 | /*********************/ 64 | DEF_ENC_SUBINSN(SS2_storeh_io, SUBINSN_S2, "00i iisssstttt") 65 | DEF_ENC_SUBINSN(SS2_storew_sp, SUBINSN_S2, "010 0iiiiitttt") 66 | DEF_ENC_SUBINSN(SS2_stored_sp, SUBINSN_S2, "010 1iiiiiittt") 67 | 68 | DEF_ENC_SUBINSN(SS2_storewi0, SUBINSN_S2, "100 00ssssiiii") 69 | DEF_ENC_SUBINSN(SS2_storewi1, SUBINSN_S2, "100 01ssssiiii") 70 | DEF_ENC_SUBINSN(SS2_storebi0, SUBINSN_S2, "100 10ssssiiii") 71 | DEF_ENC_SUBINSN(SS2_storebi1, SUBINSN_S2, "100 11ssssiiii") 72 | 73 | DEF_ENC_SUBINSN(SS2_allocframe, SUBINSN_S2, "111 0iiiii----") 74 | 75 | 76 | 77 | /*******************/ 78 | /* A-type subinsns */ 79 | /*******************/ 80 | DEF_ENC_SUBINSN(SA1_addi, SUBINSN_A, "00i iiiiiixxxx") 81 | DEF_ENC_SUBINSN(SA1_seti, SUBINSN_A, "010 iiiiiidddd") 82 | DEF_ENC_SUBINSN(SA1_addsp, SUBINSN_A, "011 iiiiiidddd") 83 | 84 | DEF_ENC_SUBINSN(SA1_tfr, SUBINSN_A, "100 00ssssdddd") 85 | DEF_ENC_SUBINSN(SA1_inc, SUBINSN_A, "100 01ssssdddd") 86 | DEF_ENC_SUBINSN(SA1_and1, SUBINSN_A, "100 10ssssdddd") 87 | DEF_ENC_SUBINSN(SA1_dec, SUBINSN_A, "100 11ssssdddd") 88 | 89 | DEF_ENC_SUBINSN(SA1_sxth, SUBINSN_A, "101 00ssssdddd") 90 | DEF_ENC_SUBINSN(SA1_sxtb, SUBINSN_A, "101 01ssssdddd") 91 | DEF_ENC_SUBINSN(SA1_zxth, SUBINSN_A, "101 10ssssdddd") 92 | DEF_ENC_SUBINSN(SA1_zxtb, SUBINSN_A, "101 11ssssdddd") 93 | 94 | 95 | DEF_ENC_SUBINSN(SA1_addrx, SUBINSN_A, "110 00ssssxxxx") 96 | DEF_ENC_SUBINSN(SA1_cmpeqi, SUBINSN_A, "110 01ssss--ii") 97 | DEF_ENC_SUBINSN(SA1_setin1, SUBINSN_A, "110 1--0--dddd") 98 | DEF_ENC_SUBINSN(SA1_clrtnew, SUBINSN_A, "110 1--100dddd") 99 | DEF_ENC_SUBINSN(SA1_clrfnew, SUBINSN_A, "110 1--101dddd") 100 | DEF_ENC_SUBINSN(SA1_clrt, SUBINSN_A, "110 1--110dddd") 101 | DEF_ENC_SUBINSN(SA1_clrf, SUBINSN_A, "110 1--111dddd") 102 | 103 | 104 | DEF_ENC_SUBINSN(SA1_combine0i, SUBINSN_A, "111 -0-ii00ddd") 105 | DEF_ENC_SUBINSN(SA1_combine1i, SUBINSN_A, "111 -0-ii01ddd") 106 | DEF_ENC_SUBINSN(SA1_combine2i, SUBINSN_A, "111 -0-ii10ddd") 107 | DEF_ENC_SUBINSN(SA1_combine3i, SUBINSN_A, "111 -0-ii11ddd") 108 | DEF_ENC_SUBINSN(SA1_combinezr, SUBINSN_A, "111 -1ssss0ddd") 109 | DEF_ENC_SUBINSN(SA1_combinerz, SUBINSN_A, "111 -1ssss1ddd") 110 | 111 | 112 | 113 | 114 | /* maybe R=cmpeq ? */ 115 | 116 | 117 | /* Add a group of NCJ: if (R.new==#0) jump:hint #r9 */ 118 | /* Add a group of NCJ: if (R.new!=#0) jump:hint #r9 */ 119 | /* NCJ goes with LD1, LD2 */ 120 | 121 | 122 | 123 | 124 | DEF_FIELD32("---! !!!! !!!!!!!! EE------ --------",SUBFIELD_B_SLOT1,"B: Slot1 Instruction") 125 | DEF_FIELD32("---- ---- -------- EE-!!!!! !!!!!!!!",SUBFIELD_A_SLOT0,"A: Slot0 Instruction") 126 | 127 | 128 | /* DEF_PACKED32(TAG, CLASSA, CLASSB, ENCSTR) */ 129 | 130 | DEF_PACKED32(P2_PACKED_L1_L1, SUBINSN_L1, SUBINSN_L1, "000B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 131 | DEF_PACKED32(P2_PACKED_L1_L2, SUBINSN_L2, SUBINSN_L1, "000B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 132 | DEF_PACKED32(P2_PACKED_L2_L2, SUBINSN_L2, SUBINSN_L2, "001B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 133 | DEF_PACKED32(P2_PACKED_A_A, SUBINSN_A, SUBINSN_A, "001B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 134 | 135 | DEF_PACKED32(P2_PACKED_L1_A, SUBINSN_L1, SUBINSN_A, "010B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 136 | DEF_PACKED32(P2_PACKED_L2_A, SUBINSN_L2, SUBINSN_A, "010B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 137 | DEF_PACKED32(P2_PACKED_S1_A, SUBINSN_S1, SUBINSN_A, "011B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 138 | DEF_PACKED32(P2_PACKED_S2_A, SUBINSN_S2, SUBINSN_A, "011B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 139 | 140 | DEF_PACKED32(P2_PACKED_S1_L1, SUBINSN_S1, SUBINSN_L1, "100B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 141 | DEF_PACKED32(P2_PACKED_S1_L2, SUBINSN_S1, SUBINSN_L2, "100B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 142 | DEF_PACKED32(P2_PACKED_S1_S1, SUBINSN_S1, SUBINSN_S1, "101B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 143 | DEF_PACKED32(P2_PACKED_S1_S2, SUBINSN_S2, SUBINSN_S1, "101B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 144 | 145 | DEF_PACKED32(P2_PACKED_S2_L1, SUBINSN_S2, SUBINSN_L1, "110B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 146 | DEF_PACKED32(P2_PACKED_S2_L2, SUBINSN_S2, SUBINSN_L2, "110B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 147 | DEF_PACKED32(P2_PACKED_S2_S2, SUBINSN_S2, SUBINSN_S2, "111B BBBB BBBB BBBB EE0A AAAA AAAA AAAA") 148 | 149 | DEF_PACKED32(P2_PACKED_RESERVED, SUBINSN_INVALID, SUBINSN_INVALID, "111B BBBB BBBB BBBB EE1A AAAA AAAA AAAA") 150 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/imported/iclass.def: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* DEF_*(TYPE,SLOTS,UNITS) */ 19 | DEF_PP_ICLASS32(EXTENDER,0123,LDST|SUNIT|MUNIT) /* 0 */ 20 | DEF_PP_ICLASS32(CJ,0123,CTRLFLOW) /* 1 */ 21 | DEF_PP_ICLASS32(NCJ,01,LDST|CTRLFLOW) /* 2 */ 22 | DEF_PP_ICLASS32(V4LDST,01,LDST) /* 3 */ 23 | DEF_PP_ICLASS32(V2LDST,01,LDST) /* 4 */ 24 | DEF_PP_ICLASS32(J,0123,CTRLFLOW) /* 5 */ 25 | DEF_PP_ICLASS32(CR,3,SUNIT) /* 6 */ 26 | DEF_PP_ICLASS32(ALU32_2op,0123,LDST|SUNIT|MUNIT) /* 7 */ 27 | DEF_PP_ICLASS32(S_2op,23,SUNIT|MUNIT) /* 8 */ 28 | DEF_PP_ICLASS32(LD,01,LDST) /* 9 */ 29 | DEF_PP_ICLASS32(ST,01,LDST) /* 10 */ 30 | DEF_PP_ICLASS32(ALU32_ADDI,0123,LDST|SUNIT|MUNIT) /* 11 */ 31 | DEF_PP_ICLASS32(S_3op,23,SUNIT|MUNIT) /* 12 */ 32 | DEF_PP_ICLASS32(ALU64,23,SUNIT|MUNIT) /* 13 */ 33 | DEF_PP_ICLASS32(M,23,SUNIT|MUNIT) /* 14 */ 34 | DEF_PP_ICLASS32(ALU32_3op,0123,LDST|SUNIT|MUNIT) /* 15 */ 35 | 36 | DEF_EE_ICLASS32(EE0,01,INVALID) /* 0 */ 37 | DEF_EE_ICLASS32(EE1,01,INVALID) /* 1 */ 38 | DEF_EE_ICLASS32(EE2,01,INVALID) /* 2 */ 39 | DEF_EE_ICLASS32(EE3,01,INVALID) /* 3 */ 40 | DEF_EE_ICLASS32(EE4,01,INVALID) /* 4 */ 41 | DEF_EE_ICLASS32(EE5,01,INVALID) /* 5 */ 42 | DEF_EE_ICLASS32(EE6,01,INVALID) /* 6 */ 43 | DEF_EE_ICLASS32(EE7,01,INVALID) /* 7 */ 44 | DEF_EE_ICLASS32(EE8,01,INVALID) /* 8 */ 45 | DEF_EE_ICLASS32(EE9,01,INVALID) /* 9 */ 46 | DEF_EE_ICLASS32(EEA,01,INVALID) /* 10 */ 47 | DEF_EE_ICLASS32(EEB,01,INVALID) /* 11 */ 48 | DEF_EE_ICLASS32(EEC,01,INVALID) /* 12 */ 49 | DEF_EE_ICLASS32(EED,01,INVALID) /* 13 */ 50 | DEF_EE_ICLASS32(EEE,01,INVALID) /* 14 */ 51 | DEF_EE_ICLASS32(EEF,01,INVALID) /* 15 */ 52 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/insn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | #define INSTRUCTIONS_MAX 7 /* 2 pairs + loopend */ 28 | #define REG_OPERANDS_MAX 5 29 | #define IMMEDS_MAX 2 30 | 31 | struct Instruction; 32 | struct Packet; 33 | struct DisasContext; 34 | 35 | struct Instruction { 36 | uint8_t regno[REG_OPERANDS_MAX]; /* reg operands including predicates */ 37 | uint16_t opcode; 38 | 39 | uint32_t iclass : 6; 40 | uint32_t slot : 3; 41 | uint32_t part1 : 1; /* 42 | * cmp-jumps are split into two insns. 43 | * set for the compare and clear for the jump 44 | */ 45 | uint32_t extension_valid : 1; /* Has a constant extender attached */ 46 | uint32_t which_extended : 1; /* If has an extender, which immediate */ 47 | uint32_t is_endloop : 1; /* This is an end of loop */ 48 | uint32_t new_value_producer_slot : 4; 49 | uint32_t hvx_resource : 8; 50 | int32_t immed[IMMEDS_MAX]; /* immediate field */ 51 | }; 52 | 53 | typedef struct Instruction Insn; 54 | 55 | struct Packet { 56 | uint16_t num_insns; 57 | uint16_t encod_pkt_size_in_bytes; 58 | 59 | /* Pre-decodes about COF */ 60 | uint32_t pkt_has_cof : 1; /* Has any change-of-flow */ 61 | uint32_t pkt_has_endloop : 1; 62 | 63 | uint32_t pkt_has_dczeroa : 1; 64 | 65 | uint32_t pkt_has_store_s0 : 1; 66 | uint32_t pkt_has_store_s1 : 1; 67 | 68 | uint32_t pkt_has_hvx : 1; 69 | uint32_t pkt_has_extension : 1; 70 | 71 | Insn insn[INSTRUCTIONS_MAX]; 72 | }; 73 | 74 | typedef struct Packet Packet; 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/mmvec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #define MAX_VEC_SIZE_LOGBYTES 7 8 | #define MAX_VEC_SIZE_BYTES (1 << MAX_VEC_SIZE_LOGBYTES) 9 | 10 | #define NUM_VREGS 32 11 | #define NUM_QREGS 4 12 | 13 | typedef uint32_t VRegMask; /* at least NUM_VREGS bits */ 14 | typedef uint32_t QRegMask; /* at least NUM_QREGS bits */ 15 | 16 | #define VECTOR_SIZE_BYTE (fVECSIZE()) 17 | 18 | typedef union { 19 | uint64_t ud[MAX_VEC_SIZE_BYTES / 8]; 20 | int64_t d[MAX_VEC_SIZE_BYTES / 8]; 21 | uint32_t uw[MAX_VEC_SIZE_BYTES / 4]; 22 | int32_t w[MAX_VEC_SIZE_BYTES / 4]; 23 | uint16_t uh[MAX_VEC_SIZE_BYTES / 2]; 24 | int16_t h[MAX_VEC_SIZE_BYTES / 2]; 25 | uint8_t ub[MAX_VEC_SIZE_BYTES / 1]; 26 | int8_t b[MAX_VEC_SIZE_BYTES / 1]; 27 | } MMVector; 28 | 29 | typedef union { 30 | uint64_t ud[2 * MAX_VEC_SIZE_BYTES / 8]; 31 | int64_t d[2 * MAX_VEC_SIZE_BYTES / 8]; 32 | uint32_t uw[2 * MAX_VEC_SIZE_BYTES / 4]; 33 | int32_t w[2 * MAX_VEC_SIZE_BYTES / 4]; 34 | uint16_t uh[2 * MAX_VEC_SIZE_BYTES / 2]; 35 | int16_t h[2 * MAX_VEC_SIZE_BYTES / 2]; 36 | uint8_t ub[2 * MAX_VEC_SIZE_BYTES / 1]; 37 | int8_t b[2 * MAX_VEC_SIZE_BYTES / 1]; 38 | MMVector v[2]; 39 | } MMVectorPair; 40 | 41 | typedef union { 42 | uint64_t ud[MAX_VEC_SIZE_BYTES / 8 / 8]; 43 | int64_t d[MAX_VEC_SIZE_BYTES / 8 / 8]; 44 | uint32_t uw[MAX_VEC_SIZE_BYTES / 4 / 8]; 45 | int32_t w[MAX_VEC_SIZE_BYTES / 4 / 8]; 46 | uint16_t uh[MAX_VEC_SIZE_BYTES / 2 / 8]; 47 | int16_t h[MAX_VEC_SIZE_BYTES / 2 / 8]; 48 | uint8_t ub[MAX_VEC_SIZE_BYTES / 1 / 8]; 49 | int8_t b[MAX_VEC_SIZE_BYTES / 1 / 8]; 50 | } MMQReg; 51 | 52 | typedef struct { 53 | MMVector data; 54 | MMVector mask; 55 | MMVectorPair offsets; 56 | int size; 57 | target_ulong va_base; 58 | target_ulong va[MAX_VEC_SIZE_BYTES]; 59 | int oob_access; 60 | int op; 61 | int op_size; 62 | } VTCMStoreLog; 63 | 64 | /* Types of vector register assignment */ 65 | enum { 66 | EXT_DFL, /* Default */ 67 | EXT_NEW, /* New - value used in the same packet */ 68 | EXT_TMP /* Temp - value used but not stored to register */ 69 | }; 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/opcodes.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * opcodes.c 20 | * 21 | * data tables generated automatically 22 | * Maybe some functions too 23 | */ 24 | 25 | #include "third_party/qemu-hexagon/opcodes.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "third_party/qemu-hexagon/decode.h" 33 | 34 | extern __thread jmp_buf decode_jmp_buf; 35 | #define ASSERT_AND_ABORT(condition) \ 36 | if (!(condition)) { \ 37 | longjmp(decode_jmp_buf, 1); \ 38 | } 39 | 40 | #define VEC_DESCR(A, B, C) DESCR(A, B, C) 41 | #define DONAME(X) #X 42 | 43 | const char *const opcode_names[] = { 44 | #define OPCODE(IID) DONAME(IID) 45 | #include "opcodes_def_generated.h" 46 | NULL 47 | #undef OPCODE 48 | }; 49 | 50 | const char *const opcode_reginfo[] = { 51 | #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ 52 | #define REGINFO(TAG, REGINFO, RREGS, WREGS) REGINFO, 53 | #include "op_regs_generated.h" 54 | NULL 55 | #undef REGINFO 56 | #undef IMMINFO 57 | }; 58 | 59 | const char *const opcode_rregs[] = { 60 | #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ 61 | #define REGINFO(TAG, REGINFO, RREGS, WREGS) RREGS, 62 | #include "op_regs_generated.h" 63 | NULL 64 | #undef REGINFO 65 | #undef IMMINFO 66 | }; 67 | 68 | const char *const opcode_wregs[] = { 69 | #define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ 70 | #define REGINFO(TAG, REGINFO, RREGS, WREGS) WREGS, 71 | #include "op_regs_generated.h" 72 | NULL 73 | #undef REGINFO 74 | #undef IMMINFO 75 | }; 76 | 77 | const char *const opcode_short_semantics[] = { 78 | #define DEF_SHORTCODE(TAG, SHORTCODE) [TAG] = #SHORTCODE, 79 | #include "shortcode_generated.h" 80 | #undef DEF_SHORTCODE 81 | NULL}; 82 | 83 | DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB); 84 | 85 | static void init_attribs(int tag, ...) { 86 | va_list ap; 87 | int attr; 88 | va_start(ap, tag); 89 | while ((attr = va_arg(ap, int)) != 0) { 90 | set_bit(attr, opcode_attribs[tag]); 91 | } 92 | } 93 | 94 | const OpcodeEncoding opcode_encodings[] = { 95 | #define DEF_ENC32(OPCODE, ENCSTR) [OPCODE] = {.encoding = ENCSTR}, 96 | 97 | #define DEF_ENC_SUBINSN(OPCODE, CLASS, ENCSTR) \ 98 | [OPCODE] = {.encoding = ENCSTR, .enc_class = CLASS}, 99 | 100 | #define DEF_EXT_ENC(OPCODE, CLASS, ENCSTR) \ 101 | [OPCODE] = {.encoding = ENCSTR, .enc_class = CLASS}, 102 | 103 | #include "third_party/qemu-hexagon/imported/encode.def" 104 | 105 | #undef DEF_ENC32 106 | #undef DEF_ENC_SUBINSN 107 | #undef DEF_EXT_ENC 108 | }; 109 | 110 | void opcode_init(void) { 111 | init_attribs(0, 0); 112 | 113 | #define ATTRIBS(...) , ##__VA_ARGS__, 0 114 | #define OP_ATTRIB(TAG, ARGS) init_attribs(TAG ARGS); 115 | #include "op_attribs_generated.h" 116 | #undef OP_ATTRIB 117 | #undef ATTRIBS 118 | 119 | decode_init(); 120 | } 121 | 122 | #define NEEDLE "IMMEXT(" 123 | 124 | int opcode_which_immediate_is_extended(Opcode opcode) { 125 | const char *p; 126 | 127 | ASSERT_AND_ABORT(opcode < XX_LAST_OPCODE); 128 | ASSERT_AND_ABORT(GET_ATTRIB(opcode, A_EXTENDABLE)); 129 | 130 | p = opcode_short_semantics[opcode]; 131 | p = strstr(p, NEEDLE); 132 | ASSERT_AND_ABORT(p); 133 | p += strlen(NEEDLE); 134 | while (isspace(*p)) { 135 | p++; 136 | } 137 | /* lower is always imm 0, upper always imm 1. */ 138 | if (islower(*p)) { 139 | return 0; 140 | } else if (isupper(*p)) { 141 | return 1; 142 | } else { 143 | ASSERT_AND_ABORT(0); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/opcodes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "third_party/qemu-hexagon/attribs.h" 25 | #include "third_party/qemu-hexagon/bitmap.h" 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | typedef enum { 32 | #define OPCODE(IID) IID 33 | #include "opcodes_def_generated.h" 34 | XX_LAST_OPCODE 35 | #undef OPCODE 36 | } Opcode; 37 | 38 | typedef enum { 39 | NORMAL, 40 | HALF, 41 | SUBINSN_A, 42 | SUBINSN_L1, 43 | SUBINSN_L2, 44 | SUBINSN_S1, 45 | SUBINSN_S2, 46 | EXT_noext, 47 | EXT_mmvec, 48 | XX_LAST_ENC_CLASS 49 | } EncClass; 50 | 51 | extern const char *const opcode_names[]; 52 | 53 | extern const char *const opcode_reginfo[]; 54 | extern const char *const opcode_rregs[]; 55 | extern const char *const opcode_wregs[]; 56 | 57 | typedef struct { 58 | const char *const encoding; 59 | const EncClass enc_class; 60 | } OpcodeEncoding; 61 | 62 | extern const OpcodeEncoding opcode_encodings[XX_LAST_OPCODE]; 63 | 64 | extern DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB); 65 | 66 | extern void opcode_init(void); 67 | 68 | extern int opcode_which_immediate_is_extended(Opcode opcode); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/reg_fields.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #include "reg_fields.h" 19 | 20 | const RegField reg_field_info[] = { 21 | #define DEF_REG_FIELD(TAG, START, WIDTH) {START, WIDTH}, 22 | #include "reg_fields_def.h" 23 | {0, 0} 24 | #undef DEF_REG_FIELD 25 | }; 26 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/reg_fields.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | #ifndef HEXAGON_REG_FIELDS_H 19 | #define HEXAGON_REG_FIELDS_H 20 | 21 | typedef struct { 22 | int offset; 23 | int width; 24 | } RegField; 25 | 26 | extern const RegField reg_field_info[]; 27 | 28 | enum { 29 | #define DEF_REG_FIELD(TAG, START, WIDTH) REG_FIELD_##TAG, 30 | #include "reg_fields_def.h" 31 | NUM_REG_FIELDS 32 | #undef DEF_REG_FIELD 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /third_party/qemu-hexagon/reg_fields_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /* 19 | * For registers that have individual fields, explain them here 20 | * DEF_REG_FIELD(tag, 21 | * bit start offset, 22 | * width 23 | */ 24 | 25 | /* USR fields */ 26 | DEF_REG_FIELD(USR_OVF, 0, 1) 27 | DEF_REG_FIELD(USR_FPINVF, 1, 1) 28 | DEF_REG_FIELD(USR_FPDBZF, 2, 1) 29 | DEF_REG_FIELD(USR_FPOVFF, 3, 1) 30 | DEF_REG_FIELD(USR_FPUNFF, 4, 1) 31 | DEF_REG_FIELD(USR_FPINPF, 5, 1) 32 | 33 | DEF_REG_FIELD(USR_LPCFG, 8, 2) 34 | 35 | DEF_REG_FIELD(USR_FPRND, 22, 2) 36 | 37 | DEF_REG_FIELD(USR_FPINVE, 25, 1) 38 | DEF_REG_FIELD(USR_FPDBZE, 26, 1) 39 | DEF_REG_FIELD(USR_FPOVFE, 27, 1) 40 | DEF_REG_FIELD(USR_FPUNFE, 28, 1) 41 | DEF_REG_FIELD(USR_FPINPE, 29, 1) 42 | DEF_REG_FIELD(USR_PFA, 31, 1) /* read-only */ 43 | --------------------------------------------------------------------------------