├── .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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------