221 lines
6.3 KiB
C
221 lines
6.3 KiB
C
// SPDX-FileCopyrightText: 2021 Rot127 <unisono@quyllur.org>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
// LLVM commit: 96e220e6886868d6663d966ecc396befffc355e7
|
|
// LLVM commit date: 2022-01-05 11:01:52 +0000 (ISO 8601 format)
|
|
// Date of code generation: 2022-09-12 14:26:04-04:00
|
|
//========================================
|
|
// The following code is generated.
|
|
// Do not edit. Repository of code generator:
|
|
// https://github.com/rizinorg/rz-hexagon
|
|
|
|
#include <rz_types.h>
|
|
#include <rz_util.h>
|
|
#include <rz_asm.h>
|
|
#include <rz_lib.h>
|
|
#include <rz_util/rz_print.h>
|
|
#include <rz_vector.h>
|
|
#include "hexagon.h"
|
|
#include "hexagon_insn.h"
|
|
#include "hexagon_arch.h"
|
|
|
|
static RZ_OWN RzPVector /*<RzAsmTokenPattern *>*/ *get_token_patterns(HexState *state) {
|
|
RzPVector *pvec = state->token_patterns;
|
|
if (pvec) {
|
|
return pvec;
|
|
}
|
|
|
|
pvec = rz_pvector_new(rz_asm_token_pattern_free);
|
|
|
|
RzAsmTokenPattern *pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_META;
|
|
pat->pattern = strdup(
|
|
"^[\\[\\?\\/\\|\\\\\\{┌│└]|" // Packet prefix
|
|
"(∎|[<\\}])[\\s:]endloop[01]{1,2}" // Endloop markers
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_META;
|
|
pat->pattern = strdup(
|
|
"\\#{1,2}|\\}$|" // Immediate prefix, Closing packet bracket
|
|
"\\.new|:n?t|:raw|<err>" // .new and jump hints
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_REGISTER;
|
|
pat->pattern = strdup(
|
|
"[CNPRMQVO]\\d{1,2}(:\\d{1,2})?(in)?" // Registers and double registers
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_REGISTER;
|
|
pat->pattern = strdup(
|
|
"GP|HTID|UGP|LR|FP|SP" // Other regs
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_NUMBER;
|
|
pat->pattern = strdup(
|
|
"0x(\\d|[abcdef])+" // Hexadecimal numbers
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_MNEMONIC;
|
|
pat->pattern = strdup(
|
|
"\\w+_\\w+|[a-zA-Z]+\\d+[a-zA-Z]*" // Mnemonics with a decimal number in the name.
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_NUMBER;
|
|
pat->pattern = strdup(
|
|
"\\d+" // Decimal numbers
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_SEPARATOR;
|
|
pat->pattern = strdup(
|
|
"\\s+|" // Spaces and tabs
|
|
"[,;\\.\\(\\)\\{\\}:]" // Brackets and others
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_OPERATOR;
|
|
pat->pattern = strdup(
|
|
"[+*&+?=!^\\/|-]{1,2}" // +,-,=,],[, ! (not the packet prefix)
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_OPERATOR;
|
|
pat->pattern = strdup(
|
|
"\\]|\\[|<{1,2}|>{1,2}" // +,-,=,],[, ! (not the packet prefix)
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
pat = RZ_NEW0(RzAsmTokenPattern);
|
|
pat->type = RZ_ASM_TOKEN_MNEMONIC;
|
|
pat->pattern = strdup(
|
|
"\\w+" // Alphanumeric mnemonics
|
|
);
|
|
rz_pvector_push(pvec, pat);
|
|
|
|
return pvec;
|
|
}
|
|
|
|
/**
|
|
* \brief Setter for the plugins RzConfig nodes.
|
|
*
|
|
* \param user The user of the RzConfig node. If this callback is called by Core \p user = RzCore.
|
|
* If it is called by the plugins config setup \p user = HexState.
|
|
* \param data The node to set. Again, if called by RzCore \p date = Node from RzCore config.
|
|
* If it is called by the plugins config setup \p data = a plugins config node.
|
|
* \return bool True if the config was set. False otherwise.
|
|
*/
|
|
static bool hex_cfg_set(void *user, void *data) {
|
|
rz_return_val_if_fail(user && data, false);
|
|
HexState *state = hexagon_get_state();
|
|
if (!state) {
|
|
return false;
|
|
}
|
|
RzConfig *pcfg = state->cfg;
|
|
|
|
RzConfigNode *cnode = (RzConfigNode *)data; // Config node from core.
|
|
RzConfigNode *pnode = rz_config_node_get(pcfg, cnode->name); // Config node of plugin.
|
|
if (pnode == cnode) {
|
|
return true;
|
|
}
|
|
if (cnode) {
|
|
pnode->i_value = cnode->i_value;
|
|
pnode->value = cnode->value;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool hexagon_init(void **user) {
|
|
HexState *state = hexagon_get_state();
|
|
rz_return_val_if_fail(state, false);
|
|
|
|
*user = state; // user = RzAsm.plugin_data
|
|
state->cfg = rz_config_new(state);
|
|
rz_return_val_if_fail(state->cfg, false);
|
|
|
|
RzConfig *cfg = state->cfg; // Rename for SETCB macros.
|
|
// Add nodes
|
|
SETCB("plugins.hexagon.imm.hash", "true", &hex_cfg_set, "Display ## before 32bit immediates and # before immidiates with other width.");
|
|
SETCB("plugins.hexagon.imm.sign", "true", &hex_cfg_set, "True: Print them with sign. False: Print signed immediates in unsigned representation.");
|
|
SETCB("plugins.hexagon.sdk", "false", &hex_cfg_set, "Print packet syntax in objdump style.");
|
|
SETCB("plugins.hexagon.reg.alias", "true", &hex_cfg_set, "Print the alias of registers (Alias from C0 = SA0).");
|
|
|
|
state->token_patterns = get_token_patterns(state);
|
|
rz_asm_compile_token_patterns(state->token_patterns);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool hexagon_fini(void *user) {
|
|
HexState *state = (HexState *)user;
|
|
rz_return_val_if_fail(state, false);
|
|
|
|
if (state->token_patterns) {
|
|
rz_pvector_free(state->token_patterns);
|
|
state->token_patterns = NULL;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
RZ_API RZ_BORROW RzConfig *hexagon_get_config(void) {
|
|
HexState *state = hexagon_get_state();
|
|
rz_return_val_if_fail(state, NULL);
|
|
return state->cfg;
|
|
}
|
|
|
|
/**
|
|
* \brief Disassembles a hexagon opcode, write info to op and returns its size.
|
|
*
|
|
* \param a The current RzAsm struct.
|
|
* \param op The RzAsmOp which is be filled with the reversed opcode information.
|
|
* \param buf The buffer with the opcode.
|
|
* \param l The size to read from the buffer.
|
|
* \return int Size of the reversed opcode.
|
|
*/
|
|
static int disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int l) {
|
|
rz_return_val_if_fail(a && op && buf, -1);
|
|
if (l < 4) {
|
|
return -1;
|
|
}
|
|
ut32 addr = (ut32)a->pc;
|
|
HexReversedOpcode rev = { .action = HEXAGON_DISAS, .ana_op = NULL, .asm_op = op };
|
|
|
|
hexagon_reverse_opcode(a, &rev, buf, addr);
|
|
return op->size;
|
|
}
|
|
|
|
RzAsmPlugin rz_asm_plugin_hexagon = {
|
|
.name = "hexagon",
|
|
.arch = "hexagon",
|
|
.author = "Rot127",
|
|
.license = "LGPL3",
|
|
.bits = 32,
|
|
.desc = "Qualcomm Hexagon (QDSP6) V6",
|
|
.init = &hexagon_init,
|
|
.fini = hexagon_fini,
|
|
.disassemble = &disassemble,
|
|
.get_config = &hexagon_get_config,
|
|
};
|
|
|
|
#ifndef RZ_PLUGIN_INCORE
|
|
RZ_API RzLibStruct rizin_plugin = {
|
|
.type = RZ_LIB_TYPE_ASM,
|
|
.data = &rz_asm_plugin_hexagon
|
|
};
|
|
#endif
|