mirror of
https://github.com/rizinorg/rizin
synced 2026-08-22 20:26:16 -04:00
Pseudo refactoring (#1308)
* License fix * Implemented common pseudo * Refactored MIPS pseudo * Refactored ARM pseudo * Refactored AVR pseudo * Refactored 6502 pseudo * Refactored dalvik pseudo * Refactored arm64 pseudo * Refactored z80 pseudo * Refactored TMS320 pseudo * Refactored v850 pseudo * Refactored SuperH pseudo * Refactored Motorola 68K pseudo * Avoid selecting a pseudo plugin when the arch is not found. * rz_parse_parse -> rz_parse_pseudocode
This commit is contained in:
parent
ebd7b7b06b
commit
35558f4180
33 changed files with 1834 additions and 2139 deletions
|
|
@ -23,13 +23,8 @@ static RzAsmPlugin *asm_static_plugins[] = { RZ_ASM_STATIC_PLUGINS };
|
|||
|
||||
static void parseHeap(RzParse *p, RzStrBuf *s) {
|
||||
char *op_buf_asm = rz_strbuf_get(s);
|
||||
size_t len = rz_strbuf_length(s);
|
||||
char *out = malloc(64 + (len * 2));
|
||||
char *out = rz_parse_pseudocode(p, op_buf_asm);
|
||||
if (out) {
|
||||
*out = 0;
|
||||
strcpy(out, op_buf_asm);
|
||||
// XXX we shouldn't pad here because we have t orefactor the RzParse API to handle boundaries and chunks properly
|
||||
rz_parse_parse(p, op_buf_asm, out);
|
||||
rz_strbuf_set(s, out);
|
||||
free(out);
|
||||
}
|
||||
|
|
@ -575,7 +570,11 @@ RZ_API int rz_asm_assemble(RzAsm *a, RzAsmOp *op, const char *buf) {
|
|||
return 0;
|
||||
}
|
||||
if (a->ifilter) {
|
||||
rz_parse_parse(a->ifilter, buf, b);
|
||||
char *tmp = rz_parse_pseudocode(a->ifilter, buf);
|
||||
if (tmp) {
|
||||
free(b);
|
||||
b = tmp;
|
||||
}
|
||||
}
|
||||
rz_str_case(b, 0); // to-lower
|
||||
memset(op, 0, sizeof(RzAsmOp));
|
||||
|
|
@ -659,8 +658,11 @@ RZ_API RzAsmCode *rz_asm_mdisassemble_hexstr(RzAsm *a, RzParse *p, const char *h
|
|||
}
|
||||
RzAsmCode *ret = rz_asm_mdisassemble(a, buf, (ut64)len);
|
||||
if (ret && p) {
|
||||
// XXX this can crash
|
||||
rz_parse_parse(p, ret->assembly, ret->assembly);
|
||||
char *tmp = rz_parse_pseudocode(p, ret->assembly);
|
||||
if (tmp) {
|
||||
free(ret->assembly);
|
||||
ret->assembly = tmp;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return ret;
|
||||
|
|
@ -987,9 +989,6 @@ RZ_API RzAsmCode *rz_asm_massemble(RzAsm *a, const char *assembly) {
|
|||
} else { /* Instruction */
|
||||
char *str = ptr_start;
|
||||
rz_str_trim(str);
|
||||
if (a->ifilter) {
|
||||
rz_parse_parse(a->ifilter, ptr_start, ptr_start);
|
||||
}
|
||||
if (acode->equs) {
|
||||
if (!*ptr_start) {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ static void loadGP(RzCore *core) {
|
|||
ut64 gp = rz_num_math(core->num, "loc._gp");
|
||||
if (!gp || gp == UT64_MAX) {
|
||||
rz_config_set(core->config, "analysis.roregs", "zero");
|
||||
rz_core_cmd0(core, "10aes@entry0");
|
||||
ut64 addr = rz_num_math(core->num, "entry");
|
||||
rz_core_seek_opt(core, addr, true, false);
|
||||
rz_core_debug_step_one(core, 10);
|
||||
rz_config_set(core->config, "analysis.roregs", "zero,gp");
|
||||
gp = rz_reg_getv(core->analysis->reg, "gp");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1637,9 +1637,8 @@ static void core_analysis_bytes(RzCore *core, const ut8 *buf, int len, int nops,
|
|||
pj_ks(pj, "disasm", strsub);
|
||||
// apply pseudo if needed
|
||||
{
|
||||
char *pseudo = calloc(128 + strlen(strsub), 3);
|
||||
rz_parse_parse(core->parser, strsub, pseudo);
|
||||
if (pseudo && *pseudo) {
|
||||
char *pseudo = rz_parse_pseudocode(core->parser, strsub);
|
||||
if (RZ_STR_ISNOTEMPTY(pseudo)) {
|
||||
pj_ks(pj, "pseudo", pseudo);
|
||||
}
|
||||
free(pseudo);
|
||||
|
|
@ -1798,9 +1797,8 @@ static void core_analysis_bytes(RzCore *core, const ut8 *buf, int len, int nops,
|
|||
}
|
||||
printline("disasm", "%s\n", disasm);
|
||||
{
|
||||
char *pseudo = calloc(128 + strlen(disasm), 3);
|
||||
rz_parse_parse(core->parser, disasm, pseudo);
|
||||
if (pseudo && *pseudo) {
|
||||
char *pseudo = rz_parse_pseudocode(core->parser, disasm);
|
||||
if (RZ_STR_ISNOTEMPTY(pseudo)) {
|
||||
printline("pseudo", "%s\n", pseudo);
|
||||
}
|
||||
free(pseudo);
|
||||
|
|
|
|||
|
|
@ -1051,7 +1051,19 @@ static void ds_build_op_str(RDisasmState *ds, bool print_color) {
|
|||
return;
|
||||
}
|
||||
if (!ds->opstr) {
|
||||
ds->opstr = strdup(rz_asm_op_get_asm(&ds->asmop));
|
||||
const char *assembly = rz_asm_op_get_asm(&ds->asmop);
|
||||
if (ds->pseudo) {
|
||||
char *tmp = rz_parse_pseudocode(core->parser, assembly);
|
||||
if (tmp) {
|
||||
snprintf(ds->str, sizeof(ds->str), "%s", tmp);
|
||||
ds->opstr = tmp;
|
||||
} else {
|
||||
ds->opstr = strdup("");
|
||||
ds->str[0] = 0;
|
||||
}
|
||||
} else {
|
||||
ds->opstr = strdup(assembly);
|
||||
}
|
||||
}
|
||||
if (ds->opstr && core->bin && core->bin->cur) {
|
||||
RzBinPlugin *plugin = rz_bin_file_cur_plugin(core->bin->cur);
|
||||
|
|
@ -1095,12 +1107,6 @@ static void ds_build_op_str(RDisasmState *ds, bool print_color) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ds->pseudo) {
|
||||
const char *opstr = ds->opstr ? ds->opstr : rz_asm_op_get_asm(&ds->asmop);
|
||||
rz_parse_parse(core->parser, opstr, ds->str);
|
||||
free(ds->opstr);
|
||||
ds->opstr = strdup(ds->str);
|
||||
}
|
||||
ds->opstr = ds_sub_jumps(ds, ds->opstr);
|
||||
if (ds->immtrim) {
|
||||
char *res = rz_parse_immtrim(ds->opstr);
|
||||
|
|
@ -2585,10 +2591,16 @@ static int ds_disassemble(RDisasmState *ds, ut8 *buf, int len) {
|
|||
ds->oplen = ds->asmop.size;
|
||||
}
|
||||
if (ds->pseudo) {
|
||||
rz_parse_parse(core->parser, ds->opstr ? ds->opstr : rz_asm_op_get_asm(&ds->asmop),
|
||||
ds->str);
|
||||
const char *opstr = rz_asm_op_get_asm(&ds->asmop);
|
||||
char *tmp = rz_parse_pseudocode(core->parser, opstr);
|
||||
free(ds->opstr);
|
||||
ds->opstr = strdup(ds->str);
|
||||
if (tmp) {
|
||||
snprintf(ds->str, sizeof(ds->str), "%s", tmp);
|
||||
ds->opstr = tmp;
|
||||
} else {
|
||||
ds->opstr = strdup("");
|
||||
ds->str[0] = 0;
|
||||
}
|
||||
}
|
||||
if (ds->acase) {
|
||||
rz_str_case(rz_asm_op_get_asm(&ds->asmop), 1);
|
||||
|
|
@ -5997,7 +6009,11 @@ RZ_API int rz_core_print_disasm_json(RzCore *core, ut64 addr, ut8 *buf, int nb_b
|
|||
rz_analysis_op(core->analysis, &ds->analop, at, buf + i, nb_bytes - i, RZ_ANALYSIS_OP_MASK_ALL);
|
||||
|
||||
if (ds->pseudo) {
|
||||
rz_parse_parse(core->parser, opstr, opstr);
|
||||
char *tmp = rz_parse_pseudocode(core->parser, opstr);
|
||||
if (tmp) {
|
||||
snprintf(opstr, sizeof(opstr), "%s", tmp);
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
// f = rz_analysis_get_fcn_in (core->analysis, at,
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ RZ_API bool rz_core_run_script(RzCore *core, const char *file);
|
|||
RZ_API void rz_core_seek_item_free(RzCoreSeekItem *item);
|
||||
RZ_API bool rz_core_seek(RzCore *core, ut64 addr, bool rb);
|
||||
RZ_API bool rz_core_seek_and_save(RzCore *core, ut64 addr, bool rb);
|
||||
RZ_API bool rz_core_seek_opt(RzCore *core, ut64 addr, bool rb, bool save);
|
||||
RZ_API bool rz_core_seek_opt(RzCore *core, ut64 addr, bool read_block, bool save);
|
||||
RZ_API bool rz_core_seek_mark(RzCore *core);
|
||||
RZ_API bool rz_core_seek_save(RzCore *core);
|
||||
RZ_API bool rz_core_seek_undo(RzCore *core);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ typedef struct rz_parse_plugin_t {
|
|||
char *desc;
|
||||
bool (*init)(RzParse *p, void *user);
|
||||
int (*fini)(RzParse *p, void *user);
|
||||
int (*parse)(RzParse *p, const char *data, char *str);
|
||||
bool (*parse)(RzParse *p, const char *data, RzStrBuf *sb);
|
||||
bool (*assemble)(RzParse *p, char *data, char *str);
|
||||
int (*filter)(RzParse *p, ut64 addr, RzFlag *f, char *data, char *str, int len, bool big_endian);
|
||||
bool (*subvar)(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char *data, char *str, int len);
|
||||
|
|
@ -66,7 +66,7 @@ RZ_API bool rz_parse_add(RzParse *p, RzParsePlugin *foo);
|
|||
RZ_API bool rz_parse_use(RzParse *p, const char *name);
|
||||
|
||||
/* action */
|
||||
RZ_API bool rz_parse_parse(RzParse *p, const char *data, char *str);
|
||||
RZ_API char *rz_parse_pseudocode(RzParse *p, const char *data);
|
||||
RZ_API bool rz_parse_assemble(RzParse *p, char *data, char *str); // XXX deprecate, unused and probably useless, related to write-hack
|
||||
RZ_API bool rz_parse_filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char *data, char *str, int len, bool big_endian);
|
||||
RZ_API bool rz_parse_subvar(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char *data, char *str, int len);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2015 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2015 qnix <qnix@0x80.org>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -12,177 +11,111 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
typedef enum {
|
||||
IND_IDX = 0,
|
||||
IDX_IND = 1,
|
||||
NORM = 2,
|
||||
} ADDR_TYPE;
|
||||
#include "parse_common.c"
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr, ADDR_TYPE type) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
int narg;
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ 1, "lda", "a = 1" },
|
||||
{ 2, "lda", "a = (1+2)" },
|
||||
{ 1, "ldx", "x = 1" },
|
||||
{ 2, "ldx", "x = (1+2)" },
|
||||
{ 1, "ldy", "y = 1" },
|
||||
{ 2, "ldy", "y = (1+2)" },
|
||||
{ 1, "sta", "[1] = a" },
|
||||
{ 2, "sta", "[1+2 ] = a" },
|
||||
{ 1, "stx", "[1] = x" },
|
||||
{ 2, "stx", "[1+2] = x" },
|
||||
{ 1, "sty", "[1] = y" },
|
||||
{ 2, "sty", "[1+2] = y" },
|
||||
{ 1, "dec", "1--" },
|
||||
{ 2, "dec", "(1+2)--" },
|
||||
{ 0, "dcx", "x--" },
|
||||
{ 0, "dcy", "y--" },
|
||||
{ 1, "inc", "1++" },
|
||||
{ 2, "inc", "(1+2)++" },
|
||||
{ 0, "inx", "x++" },
|
||||
{ 0, "iny", "y++" },
|
||||
{ 1, "adc", "a += 1" },
|
||||
{ 2, "adc", "a += (1+2)" },
|
||||
{ 1, "sbc", "a -= 1" },
|
||||
{ 2, "sbc", "a -= (1+2)" },
|
||||
{ 0, "pha", "push a" },
|
||||
{ 1, "and", "a &= 1" },
|
||||
{ 2, "and", "a &= (1+2)" },
|
||||
{ 1, "eor", "a ^= 1" },
|
||||
{ 2, "eor", "a ^= (1+2)" },
|
||||
{ 1, "ora", "a |= 1" },
|
||||
{ 2, "ora", "a |= (1+2)" },
|
||||
{ 0, "tax", "x = a" },
|
||||
{ 0, "tay", "y = a" },
|
||||
{ 0, "txa", "a = x" },
|
||||
{ 0, "tya", "a = y" },
|
||||
{ 0, "tsx", "x = s" },
|
||||
{ 0, "txs", "s = x" },
|
||||
{ 0, "brk", "break" },
|
||||
{ 0, "clc", "clear_carry" },
|
||||
{ 0, "cld", "clear_decimal" },
|
||||
{ 0, "cli", "clear_interrupt" },
|
||||
{ 0, "clv", "clear_overflow" },
|
||||
{ 0, "sec", "set_carry" },
|
||||
{ 0, "sed", "set_decimal" },
|
||||
{ 0, "sei", "set_interrupt" },
|
||||
{ 1, "jsr", "1()" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
if (!newstr) {
|
||||
return false;
|
||||
static RzList *_6502_tokenize(const char *assembly, size_t length);
|
||||
|
||||
static const RzPseudoGrammar _6502_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "a += (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and", "a &= (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("asl", "a = 1 << #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bcc", "if (carry == 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bcs", "if (carry != 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (eq) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bmi", "if (lt) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bne", "if (ne) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bpl", "if (gt) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brk", "break"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clc", "carry = 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cld", "decimal = 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cli", "interrupt = 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clv", "overflow = 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "cmp (1, 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cpx", "cmp (x, 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cpy", "cmp (y, 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dcx", "x--"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dcy", "y--"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dec", "(1 + 2)--"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dex", "x--"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dey", "y--"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("eor", "a ^= (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "(1 + 2)++"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "1++"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("inx", "x++"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iny", "y++"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jsr", "1 ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lda", "a = (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldx", "x = (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldy", "y = (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ora", "a |= (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("pha", "push a"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rti", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rts", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "a -= (1 + 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sec", "carry = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sed", "decimal = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sei", "interrupt = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sta", "[1 + 2] = a"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stx", "[1 + 2] = x"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sty", "[1 + 2] = y"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tax", "x = a"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tay", "y = a"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tsx", "x = s"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("txa", "a = x"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("txs", "s = x"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tya", "a = y"),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig _6502_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(_6502_lexicon, 3, _6502_tokenize);
|
||||
|
||||
RzList *_6502_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
bool insert_zero = false;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; ops[i].op != NULL; i++) {
|
||||
if (ops[i].narg) {
|
||||
if (argc - 1 != ops[i].narg) {
|
||||
continue;
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
buf[p] = ' ';
|
||||
} else if (buf[p] == '#') {
|
||||
p++;
|
||||
} else if (buf[p] == '(') {
|
||||
buf[p] = ' ';
|
||||
if (!IS_HEXCHAR(buf[p - 1])) {
|
||||
p++;
|
||||
insert_zero = true;
|
||||
}
|
||||
} else if (buf[p] == ')') {
|
||||
buf[p] = 0;
|
||||
}
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
|
||||
if (IS_DIGIT(ops[i].str[j])) {
|
||||
const char *w = argv[ops[i].str[j] - '0'];
|
||||
if (w != NULL) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
if (argc == 4 && argv[2][0] == '[') {
|
||||
strcat(newstr + k, "+");
|
||||
strcat(newstr + k + 3, argv[2]);
|
||||
}
|
||||
return true;
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
/* TODO: this is slow */
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ",");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static ADDR_TYPE addr_type(const char *str) {
|
||||
if (strchr(str, '(')) {
|
||||
char *e = strchr(str, ')');
|
||||
if (!e) {
|
||||
return NORM;
|
||||
}
|
||||
char *o = strchr(e, ',');
|
||||
return (o) ? IND_IDX : IDX_IND;
|
||||
}
|
||||
return NORM;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
char w0[256], w1[256], w2[256];
|
||||
int i, len = strlen(data);
|
||||
char *buf, *ptr, *optr;
|
||||
ADDR_TYPE atype;
|
||||
|
||||
if (len >= sizeof(w0)) {
|
||||
return false;
|
||||
}
|
||||
// malloc can be slow here :?
|
||||
if (!(buf = malloc(len + 1))) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf, data, len + 1);
|
||||
|
||||
if (*buf) {
|
||||
atype = addr_type(buf);
|
||||
rz_str_replace_char(buf, '(', ' ');
|
||||
rz_str_replace_char(buf, ')', ' ');
|
||||
*w0 = *w1 = *w2 = '\0';
|
||||
ptr = strchr(buf, ' ');
|
||||
if (!ptr) {
|
||||
ptr = strchr(buf, '\t');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w0, buf, sizeof(w0) - 1);
|
||||
strncpy(w1, ptr, sizeof(w1) - 1);
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w1, optr, sizeof(w1) - 1);
|
||||
strncpy(w2, ptr, sizeof(w2) - 1);
|
||||
}
|
||||
} else {
|
||||
strncpy(w0, buf, sizeof(w0) - 1);
|
||||
}
|
||||
|
||||
const char *wa[] = { w0, w1, w2 };
|
||||
int nw = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (wa[i][0]) {
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str, atype);
|
||||
}
|
||||
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (insert_zero) {
|
||||
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&_6502_config, assembly, sb);
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_6502_pseudo = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2015-2018 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -10,272 +11,198 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
#define MAXPSEUDOOPS 10
|
||||
int i, j, k, d;
|
||||
char ch;
|
||||
struct {
|
||||
int narg;
|
||||
char *op;
|
||||
char *str;
|
||||
int args[MAXPSEUDOOPS];
|
||||
} ops[] = {
|
||||
{ 0, "abs", "# = abs(#)", { 1, 1 } },
|
||||
{ 0, "adc", "# = # + #", { 1, 2, 3 } },
|
||||
{ 3, "add", "# = # + #", { 1, 2, 3 } },
|
||||
{ 2, "add", "# += #", { 1, 2 } },
|
||||
{ 2, "adds", "# += #", { 1, 2 } },
|
||||
{ 3, "adds", "# = # + #", { 1, 2, 3 } },
|
||||
{ 3, "addw", "# = # + #", { 1, 2, 3 } },
|
||||
{ 3, "add.w", "# = # + #", { 1, 2, 3 } },
|
||||
{ 0, "adf", "# = # + #", { 1, 2, 3 } },
|
||||
{ 0, "adrp", "# = #", { 1, 2 } },
|
||||
{ 0, "adr", "# = #", { 1, 2 } },
|
||||
{ 0, "and", "# = # & #", { 1, 2, 3 } },
|
||||
{ 0, "ands", "# &= #", { 1, 2 } },
|
||||
{ 0, "asls", "# = # << #", { 1, 2, 3 } },
|
||||
{ 0, "asl", "# = # << #", { 1, 2, 3 } },
|
||||
{ 0, "asrs", "# = # >> #", { 1, 2, 3 } },
|
||||
{ 0, "asr", "# = # >> #", { 1, 2, 3 } },
|
||||
{ 0, "b", "jmp #", { 1 } },
|
||||
{ 0, "cbz", "if !# jmp #", { 1, 2 } },
|
||||
{ 0, "cbnz", "if # jmp #", { 1, 2 } },
|
||||
{ 0, "b.w", "jmp #", { 1 } },
|
||||
{ 0, "b.gt", "jmp ifgt #", { 1 } },
|
||||
{ 0, "b.le", "jmp ifle #", { 1 } },
|
||||
{ 0, "beq lr", "ifeq ret", { 0 } },
|
||||
{ 0, "beq", "je #", { 1 } },
|
||||
{ 0, "call", "# ()", { 1 } },
|
||||
{ 0, "bl", "# ()", { 1 } },
|
||||
{ 0, "blx", "# ()", { 1 } },
|
||||
{ 0, "bx lr", "ret", { 0 } },
|
||||
{ 0, "bxeq", "je #", { 1 } },
|
||||
{ 0, "cmf", "if (# == #)", { 1, 2 } },
|
||||
{ 0, "cmn", "if (# != #)", { 1, 2 } },
|
||||
{ 0, "cmp", "if (# == #)", { 1, 2 } },
|
||||
{ 0, "fcmp", "if (# == #)", { 1, 2 } },
|
||||
{ 0, "tst", "if ((# & #) == 0)", { 1, 2 } },
|
||||
{ 0, "dvf", "# = # / #", { 1, 2, 3 } },
|
||||
{ 0, "eor", "# = # ^ #", { 1, 2, 3 } },
|
||||
{ 1, "bkpt", "breakpoint #", { 1 } },
|
||||
{ 1, "udf", "undefined #", { 1 } },
|
||||
{ 2, "sxtb", "# = (char) #", { 1, 2 } },
|
||||
{ 2, "sxth", "# = (short) #", { 1, 2 } },
|
||||
{ 0, "fdv", "# = # / #", { 1, 2, 3 } },
|
||||
{ 0, "fml", "# = # * #", { 1, 2, 3 } },
|
||||
{ 2, "ldr", "# = #", { 1, 2 } },
|
||||
{ 2, "ldrh", "# = (word) #", { 1, 2 } },
|
||||
{ 3, "ldrh", "# = (word) # + #", { 1, 2, 3 } },
|
||||
{ 2, "ldrb", "# = (byte) #", { 1, 2 } },
|
||||
{ 3, "ldrb", "# = (byte) # + #", { 1, 2, 3 } },
|
||||
{ 2, "ldrsb", "# = (byte) #", { 1, 2 } },
|
||||
{ 2, "ldr.w", "# = #", { 1, 2 } },
|
||||
{ 2, "ldrsw", "# = #", { 1, 2 } },
|
||||
{ 3, "ldr", "# = # + #", { 1, 2, 3 } },
|
||||
{ 3, "ldrb", "# = (byte) # + #", { 1, 2, 3 } },
|
||||
{ 3, "ldrsb", "# = (byte) # + #", { 1, 2, 3 } },
|
||||
{ 3, "ldr.w", "# = # + #", { 1, 2, 3 } },
|
||||
{ 3, "ldrsw", "# = # + #", { 1, 2, 3 } },
|
||||
{ 0, "lsl", "# = # << #", { 1, 2, 3 } },
|
||||
{ 0, "lsr", "# = # >> #", { 1, 2, 3 } },
|
||||
{ 0, "mov", "# = #", { 1, 2 } },
|
||||
{ 0, "fmov", "# = #", { 1, 2 } },
|
||||
{ 0, "mvn", "# = ~#", { 1, 2 } },
|
||||
{ 0, "movz", "# = #", { 1, 2 } },
|
||||
{ 0, "movk", "# = #", { 1, 2 } },
|
||||
{ 0, "movn", "# = ~#", { 1, 2 } },
|
||||
{ 0, "neg", "# = !#", { 1, 2 } },
|
||||
{ 0, "sxtw", "# = #", { 1, 2 } },
|
||||
{ 0, "stur", "# = #", { 2, 1 } },
|
||||
{ 0, "stp", "# = (#, 2)", { 3, 1 } },
|
||||
{ 0, "ldp", "(#, 2) = 3", { 1 } },
|
||||
{ 0, "vmov.i32", "# = #", { 1, 2 } },
|
||||
{ 0, "muf", "# = # * #", { 1, 2, 3 } },
|
||||
{ 0, "mul", "# = # * #", { 1, 2, 3 } },
|
||||
{ 0, "fmul", "# = # * #", { 1, 2, 3 } },
|
||||
{ 0, "muls", "# = # * #", { 1, 2, 3 } },
|
||||
{ 0, "div", "# = # / #", { 1, 2, 3 } },
|
||||
{ 0, "fdiv", "# = # / #", { 1, 2, 3 } },
|
||||
{ 0, "udiv", "# = (unsigned) # / #", { 1, 2, 3 } },
|
||||
{ 0, "orr", "# = # | #", { 1, 2, 3 } },
|
||||
{ 0, "rmf", "# = # % #", { 1, 2, 3 } },
|
||||
{ 0, "bge", "(>=) goto #", { 1 } },
|
||||
{ 0, "sbc", "# = # - #", { 1, 2, 3 } },
|
||||
{ 0, "sqt", "# = sqrt(#)", { 1, 2 } },
|
||||
{ 0, "lsrs", "# = # >> #", { 1, 2, 3 } },
|
||||
{ 0, "lsls", "# = # << #", { 1, 2, 3 } },
|
||||
{ 0, "lsr", "# = # >> #", { 1, 2, 3 } },
|
||||
{ 0, "lsl", "# = # << #", { 1, 2, 3 } },
|
||||
{ 2, "str", "# = #", { 2, 1 } },
|
||||
{ 2, "strb", "# = (byte) #", { 2, 1 } },
|
||||
{ 2, "strh", "# = (half) #", { 2, 1 } },
|
||||
{ 2, "strh.w", "# = (half) #", { 2, 1 } },
|
||||
{ 3, "str", "# + # = #", { 2, 3, 1 } },
|
||||
{ 3, "strb", "# + # = (byte) #", { 2, 3, 1 } },
|
||||
{ 3, "strh", "# + # = (half) #", { 2, 3, 1 } },
|
||||
{ 3, "strh.w", "# + # = (half) #", { 2, 3, 1 } },
|
||||
{ 3, "sub", "# = # - #", { 1, 2, 3 } },
|
||||
{ 3, "subs", "# = # - #", { 1, 2, 3 } },
|
||||
{ 3, "fsub", "# = # - #", { 1, 2, 3 } },
|
||||
{ 2, "sub", "# -= #", { 1, 2 } }, // THUMB
|
||||
{ 2, "subs", "# -= #", { 1, 2 } }, // THUMB
|
||||
{ 0, "swp", "swap(#, 2)", { 1 } },
|
||||
/* arm thumb */
|
||||
{ 0, "movs", "# = #", { 1, 2 } },
|
||||
{ 0, "movw", "# = #", { 1, 2 } },
|
||||
{ 0, "movt", "# |= # << 16", { 1, 2 } },
|
||||
{ 0, "vmov", "# = (float) # . #", { 1, 2, 3 } },
|
||||
{ 0, "vdiv.f64", "# = (float) # / #", { 1, 2, 3 } },
|
||||
{ 0, "addw", "# = # + #", { 1, 2, 3 } },
|
||||
{ 0, "sub.w", "# = # - #", { 1, 2, 3 } },
|
||||
{ 0, "tst.w", "if ((# & #) == 0)", { 1, 2 } },
|
||||
{ 0, "lsr.w", "# = # >> #", { 1, 2, 3 } },
|
||||
{ 0, "lsl.w", "# = # << #", { 1, 2, 3 } },
|
||||
{ 0, "pop.w", "pop #", { 1 } },
|
||||
{ 0, "vpop", "pop #", { 1 } },
|
||||
{ 0, "vpush", "push #", { 1 } },
|
||||
{ 0, "push.w", "push #", { 1 } },
|
||||
{ 0, NULL }
|
||||
};
|
||||
if (!newstr) {
|
||||
return false;
|
||||
#include "parse_common.c"
|
||||
|
||||
static RzList *arm_tokenize(const char *assembly, size_t length);
|
||||
|
||||
static const RzPseudoGrammar arm_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("abs", "1 = abs(1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add.w", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adds", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addw", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adf", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adr", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adrp", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 = 2 & 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ands", "1 &= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("asl", "1 = 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("asls", "1 = 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("asr", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("asrs", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("b", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("b.gt", "if (? > ?) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("b.le", "if (? < ?) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("b.w", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (? == ?) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bge", "if (? >= ?) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bkpt", "breakpoint 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bl", "1 ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("blx", "1 ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bxeq", "if (? == ?) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("call", "1 ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cbnz", "if (1) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cbz", "if (!1) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmf", "if (1 == 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmn", "if (1 != 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "if (1 == 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div", "1 = 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dvf", "1 = 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("eor", "1 = 2 ^ 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fcmp", "if (1 == 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fdiv", "1 = 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fdv", "1 = 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fml", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fmov", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fmul", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fsub", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldp", "(1, 2) = 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldr", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldr.w", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldrb", "1 = (byte) 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldrh", "1 = (word) 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldrsb", "1 = (byte) 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldrsw", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldrsw", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsl", "1 = 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsls", "1 = 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsr", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsrs", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movk", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movn", "1 = ~2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movz", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("muf", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("muls", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mvn", "1 = ~2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = !2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("orr", "1 = 2 | 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rmf", "1 = 2 % 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sqt", "1 = sqrt(2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stp", "3 = (1, 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("str", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("strb", "2 = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("strh", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("strh.w", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stur", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subs", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("swp", "swap(1, 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sxtb", "1 = (char) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sxth", "1 = (short) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sxtw", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "if ((1 & 2) == 0)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("udf", "undefined 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("udiv", "1 = (unsigned) 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("vmov.i32", "1 = 2"),
|
||||
/* arm thumb */
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsl.w", "1 = 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsr.w", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movs", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movt", "1 |= 2 << #16"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movw", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("pop", "pop 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("pop.w", "pop 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("push", "push 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("push.w", "push 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 -= 2"), // THUMB
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub.w", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subs", "1 -= 2"), // THUMB
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tst.w", "if ((1 & 2) == 0)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("vdiv.f64", "1 = (float) 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("vmov", "1 = (float) 2 . 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("vpop", "pop(1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("vpush", "push(1)"),
|
||||
};
|
||||
|
||||
static const RzPseudoDirect arm_direct[] = {
|
||||
RZ_PSEUDO_DEFINE_DIRECT("beq lr", "if (? == ?) return"),
|
||||
RZ_PSEUDO_DEFINE_DIRECT("bx lr", "return"),
|
||||
};
|
||||
|
||||
static const RzPseudoReplace arm_replace[] = {
|
||||
RZ_PSEUDO_DEFINE_REPLACE(" + 0]", "]", 0),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("0 << 16", "0", 1),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("{", "(", 1),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("}", ")", 1),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig arm_config = RZ_PSEUDO_DEFINE_CONFIG(arm_direct, arm_lexicon, arm_replace, 5, arm_tokenize);
|
||||
|
||||
RzList *arm_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
const char *comma_replace = NULL;
|
||||
bool keep = false;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; ops[i].op; i++) {
|
||||
if (ops[i].narg) {
|
||||
if (argc - 1 != ops[i].narg) {
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
if (!keep) {
|
||||
p++;
|
||||
} else if (buf[p + 1] == ' ') {
|
||||
buf[i] = buf[p];
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
if (newstr) {
|
||||
d = 0;
|
||||
j = 0;
|
||||
ch = ops[i].str[j];
|
||||
for (j = 0, k = 0; ch != '\0'; j++, k++) {
|
||||
ch = ops[i].str[j];
|
||||
if (ch == '#') {
|
||||
if (d >= MAXPSEUDOOPS) {
|
||||
// XXX Shouldn't ever happen...
|
||||
continue;
|
||||
}
|
||||
int idx = ops[i].args[d];
|
||||
d++;
|
||||
if (idx <= 0) {
|
||||
// XXX Shouldn't ever happen...
|
||||
continue;
|
||||
}
|
||||
const char *w = argv[idx];
|
||||
if (w) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ch;
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
} else if (buf[p] == '(') {
|
||||
buf[p] = ' ';
|
||||
} else if (buf[p] == ')') {
|
||||
buf[p] = ' ';
|
||||
} else if (buf[p] == '[') {
|
||||
keep = true;
|
||||
comma_replace = " + ";
|
||||
} else if (buf[p] == ']') {
|
||||
keep = false;
|
||||
} else if (buf[p] == '{') {
|
||||
if (strchr(buf + p + 1, ',') < strchr(buf + p + 1, '}')) {
|
||||
keep = true;
|
||||
comma_replace = ", ";
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
} else if (buf[p] == '}') {
|
||||
if (!comma_replace) {
|
||||
p++;
|
||||
}
|
||||
keep = false;
|
||||
} else if ((buf[p] == 'w' || buf[p] == 'x') && buf[p + 1] == 'z' && buf[p + 2] == 'r') {
|
||||
p += 2;
|
||||
buf[p] = '0';
|
||||
}
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
rz_str_replace_char(newstr, '{', '(');
|
||||
rz_str_replace_char(newstr, '}', ')');
|
||||
return true;
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (comma_replace) {
|
||||
RzListIter *it;
|
||||
rz_list_foreach (tokens, it, buf) {
|
||||
it->data = rz_str_replace(buf, ",", comma_replace, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: this is slow */
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (!i || i == argc - 1) ? " " : ",");
|
||||
}
|
||||
rz_str_replace_char(newstr, '{', '(');
|
||||
rz_str_replace_char(newstr, '}', ')');
|
||||
return false;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
char w0[256], w1[256], w2[256], w3[256];
|
||||
int i, len = strlen(data);
|
||||
char *buf, *ptr, *optr;
|
||||
|
||||
if (len >= sizeof(w0)) {
|
||||
return false;
|
||||
}
|
||||
// malloc can be slow here :?
|
||||
if (!(buf = malloc(len + 1))) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf, data, len + 1);
|
||||
if (*buf) {
|
||||
*w0 = *w1 = *w2 = *w3 = '\0';
|
||||
ptr = strchr(buf, ' ');
|
||||
if (!ptr) {
|
||||
ptr = strchr(buf, '\t');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w0, buf, sizeof(w0) - 1);
|
||||
strncpy(w1, ptr, sizeof(w1) - 1);
|
||||
|
||||
optr = ptr;
|
||||
if (*ptr == '(') {
|
||||
ptr = strchr(ptr + 1, ')');
|
||||
}
|
||||
if (ptr && *ptr == '[') {
|
||||
ptr = strchr(ptr + 1, ']');
|
||||
}
|
||||
if (ptr && *ptr == '{') {
|
||||
ptr = strchr(ptr + 1, '}');
|
||||
}
|
||||
if (!ptr) {
|
||||
eprintf("Unbalanced bracket\n");
|
||||
free(buf);
|
||||
return false;
|
||||
}
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w1, optr, sizeof(w1) - 1);
|
||||
strncpy(w2, ptr, sizeof(w2) - 1);
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w2, optr, sizeof(w2) - 1);
|
||||
strncpy(w3, ptr, sizeof(w3) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const char *wa[] = { w0, w1, w2, w3 };
|
||||
int nw = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (wa[i][0]) {
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str);
|
||||
}
|
||||
}
|
||||
{
|
||||
char *s = strdup(str);
|
||||
s = rz_str_replace(s, "+ -", "- ", 1);
|
||||
s = rz_str_replace(s, "- -", "+ ", 1);
|
||||
strcpy(str, s);
|
||||
free(s);
|
||||
}
|
||||
free(buf);
|
||||
return true;
|
||||
static bool parse(RzParse *p, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&arm_config, assembly, sb);
|
||||
}
|
||||
|
||||
static char *subs_var_string(RzParse *p, RzAnalysisVarField *var, char *tstr, const char *oldstr, const char *reg, int delta) {
|
||||
|
|
@ -352,7 +279,7 @@ static bool subvar(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char
|
|||
rip = (char *)rz_str_casestr(tstr, "[pc, ");
|
||||
}
|
||||
|
||||
if (rip && !strchr(rip + 4, ',')) {
|
||||
if (rip) {
|
||||
rip += 4;
|
||||
char *tstr_new, *ripend = strchr(rip, ']');
|
||||
const char *neg = strchr(rip, '-');
|
||||
|
|
|
|||
|
|
@ -68,12 +68,13 @@ static int replace(int argc, const char *argv[], char *newstr) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
|
||||
int i, n;
|
||||
char w0[32];
|
||||
char w1[32];
|
||||
char w2[32];
|
||||
char w3[32];
|
||||
char str[1024] = { 0 };
|
||||
char *buf, *ptr, *optr, *num;
|
||||
|
||||
// malloc can be slow here :?
|
||||
|
|
@ -167,6 +168,7 @@ static int parse(RzParse *p, const char *data, char *str) {
|
|||
}
|
||||
}
|
||||
free(buf);
|
||||
rz_strbuf_set(sb, str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2017-2019 deroad <wargio@libero.it>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -11,210 +11,143 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
static bool replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ "add", "A += B" },
|
||||
{ "adc", "A += B + carry" },
|
||||
{ "adiw", "A+1:A += B" },
|
||||
{ "sub", "A -= B" },
|
||||
{ "subi", "A -= B" },
|
||||
{ "sbc", "A -= (B + carry)" },
|
||||
{ "sbci", "A -= (B + carry)" },
|
||||
{ "sbiw", "A+1:A -= B" },
|
||||
{ "and", "A &= B" },
|
||||
{ "andi", "A &= B" },
|
||||
{ "or", "A |= B" },
|
||||
{ "ori", "A |= B" },
|
||||
{ "eor", "A ^= B" },
|
||||
{ "com", "A = 0xff - A" },
|
||||
{ "neg", "A = -A" },
|
||||
{ "sbr", "A |= B" },
|
||||
{ "cbr", "A &= (0xff - B)" },
|
||||
{ "inc", "A++" },
|
||||
{ "dec", "A--" },
|
||||
{ "tst", "A &= A" },
|
||||
{ "clr", "A ^= A" },
|
||||
{ "ser", "A = 0xff" },
|
||||
{ "mul", "r1:r0 = A * B" },
|
||||
{ "rjmp", "goto A" },
|
||||
{ "ijmp", "goto z" },
|
||||
{ "jmp", "goto A" },
|
||||
{ "rcall", "goto A" },
|
||||
{ "icall", "goto z" },
|
||||
{ "call", "goto A" },
|
||||
{ "ret", "return" },
|
||||
{ "iret", "return_interrupt()" },
|
||||
{ "cp", "var = A - B" },
|
||||
{ "cpc", "var = A - B - carry" },
|
||||
{ "cpi", "var = A - B" },
|
||||
{ "breq", "if(!var) goto A" },
|
||||
{ "brne", "if(var) goto A" },
|
||||
{ "brsh", "if(var >= 0) goto A" },
|
||||
{ "brlo", "if(var < 0) goto A" },
|
||||
{ "brmi", "if(var < 0) goto A" },
|
||||
{ "brpl", "if(var > 0) goto A" },
|
||||
{ "brge", "if(var >= 0) goto A" },
|
||||
{ "brlt", "if(var < 0) goto A" },
|
||||
{ "mov", "A = B" },
|
||||
{ "movw", "A+1:A = B+1:B" },
|
||||
{ "ldi", "A = B" },
|
||||
{ "lds", "A = *(B)" },
|
||||
{ "ld", "A = *(B)" },
|
||||
{ "ldd", "A = *(B)" },
|
||||
{ "lpm", "r0 = z" },
|
||||
{ "in", "A = B" },
|
||||
{ "out", "A = B" },
|
||||
{ "push", "push(A)" },
|
||||
{ "pop", "A = pop()" },
|
||||
{ "lsl", "A <<= 1" },
|
||||
{ "lsr", "A >>= 1" },
|
||||
{ "rol", "A = (A << 1) | (A >> 7)" },
|
||||
{ "ror", "A = (A << 7) | (A >> 1)" },
|
||||
{ "asr", "A >>= 1" },
|
||||
{ "swap", "A = ((A & 0xf0) >> 4) | ((A & 0x0f) << 4)" },
|
||||
{ "sec", "c = 1" },
|
||||
{ "clc", "c = 0" },
|
||||
{ "sen", "n = 1" },
|
||||
{ "cln", "n = 0" },
|
||||
{ "sez", "z = 1" },
|
||||
{ "clz", "z = 0" },
|
||||
{ "sei", "i = 1" },
|
||||
{ "cli", "i = 0" },
|
||||
{ "ses", "s = 1" },
|
||||
{ "cls", "s = 0" },
|
||||
{ "sev", "v = 1" },
|
||||
{ "clv", "v = 0" },
|
||||
{ "set", "t = 1" },
|
||||
{ "clt", "t = 0" },
|
||||
{ "seh", "h = 1" },
|
||||
{ "clh", "h = 0" },
|
||||
{ "nop", "" },
|
||||
{ "halt", "_halt()" },
|
||||
{ "wdr", "_watchdog_reset()" },
|
||||
{ "std", "*(A) = B" },
|
||||
{ "st", "*(A) = B" },
|
||||
{ "sts", "*(A) = B" },
|
||||
{ NULL }
|
||||
};
|
||||
#include "parse_common.c"
|
||||
|
||||
for (i = 0; ops[i].op != NULL; i++) {
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
if (newstr != NULL) {
|
||||
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
|
||||
if (ops[i].str[j] >= 'A' && ops[i].str[j] <= 'J') {
|
||||
const char *w = argv[ops[i].str[j] - '@'];
|
||||
if (w != NULL) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
static RzList *avr_tokenize(const char *assembly, size_t length);
|
||||
|
||||
static const RzPseudoGrammar avr_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "1 += 2 + carry"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adiw", "1+#1:1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 &= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "1 &= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("asr", "1 >>= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("breq", "if(!var) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brge", "if(var >= 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brlo", "if(var < 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brlt", "if(var < 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brmi", "if(var < 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brne", "if(var) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brpl", "if(var > 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brsh", "if(var >= 0) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("call", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cbr", "1 &= (#0xff - 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clc", "c = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clh", "h = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cli", "i = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cln", "n = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clr", "1 ^= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cls", "s = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clt", "t = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clv", "v = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clz", "z = #0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("com", "1 = #0xff - 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cp", "var = 1 - 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cpc", "var = 1 - 2 - carry"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cpi", "var = 1 - 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cpse", "if(1 == 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dec", "1--"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("eor", "1 ^= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("halt", "_halt()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("icall", "goto z"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ijmp", "goto z"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("in", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "1++"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iret", "return_interrupt()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ld", "1 = *(2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldd", "1 = *(2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldi", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lds", "1 = *(2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lpm", "r0 = z"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsl", "1 <<= #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsr", "1 >>= #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movw", "1+#1:1 = 2+#1:2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "#r1:r0 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = -1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or", "1 |= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "1 |= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("out", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("pop", "1 = pop()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("push", "push(1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rcall", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ret", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rjmp", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rol", "1 = (1 << #1) | (1 >> #7)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ror", "1 = (1 << #7) | (1 >> #1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "1 -= (2 + carry)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbci", "1 -= (2 + carry)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbiw", "1+#1:1 -= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbrc", "if((1 & (#1 << 2)) != #0)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbrs", "if((1 & (#1 << 2)) != #1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbr", "1 |= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sec", "c = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("seh", "h = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sei", "i = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sen", "n = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ser", "1 = #0xff"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ses", "s = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("set", "t = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sev", "v = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sez", "z = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("st", "*(1) = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("std", "*(1) = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sts", "*(1) = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 -= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subi", "1 -= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("swap", "1 = ((1 & #0xf0) >> #4) | ((1 & #0x0f) << #4)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "1 &= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("wdr", "_watchdog_reset()"),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig avr_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(avr_lexicon, 3, avr_tokenize);
|
||||
|
||||
RzList *avr_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
bool insert_zero = false;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
p++;
|
||||
} else if (buf[p] == '(') {
|
||||
buf[p] = ' ';
|
||||
if (!IS_HEXCHAR(buf[p - 1])) {
|
||||
p++;
|
||||
insert_zero = true;
|
||||
}
|
||||
return true;
|
||||
} else if (buf[p] == ')') {
|
||||
buf[p] = 0;
|
||||
}
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
/* TODO: this is slow */
|
||||
if (newstr != NULL) {
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
|
||||
}
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (insert_zero) {
|
||||
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
#define WSZ 128
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
int i, len = strlen(data);
|
||||
char w0[WSZ];
|
||||
char w1[WSZ];
|
||||
char w2[WSZ];
|
||||
char w3[WSZ];
|
||||
char w4[WSZ];
|
||||
char *buf, *ptr, *optr;
|
||||
|
||||
// malloc can be slow here :?
|
||||
if (!(buf = malloc(len + 1))) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf, data, len + 1);
|
||||
|
||||
rz_str_trim(buf);
|
||||
if (*buf) {
|
||||
w0[0] = '\0';
|
||||
w1[0] = '\0';
|
||||
w2[0] = '\0';
|
||||
w3[0] = '\0';
|
||||
w4[0] = '\0';
|
||||
ptr = strchr(buf, ' ');
|
||||
if (!ptr) {
|
||||
ptr = strchr(buf, '\t');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w0, buf, WSZ - 1);
|
||||
strncpy(w1, ptr, WSZ - 1);
|
||||
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w1, optr, WSZ - 1);
|
||||
strncpy(w2, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w2, optr, WSZ - 1);
|
||||
strncpy(w3, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
// bonus
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w3, optr, WSZ - 1);
|
||||
strncpy(w4, ptr, WSZ - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strncpy(w0, buf, WSZ - 1);
|
||||
}
|
||||
{
|
||||
const char *wa[] = { w0, w1, w2, w3, w4 };
|
||||
int nw = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (wa[i][0] != '\0') {
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
(void)replace(nw, wa, str);
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return true;
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&avr_config, assembly, sb);
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_avr_pseudo = {
|
||||
|
|
|
|||
|
|
@ -89,8 +89,9 @@ static int tokenize(const char *in, char *out[]) {
|
|||
return count;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
|
||||
int i;
|
||||
char str[1024] = { 0 };
|
||||
char *argv[MAXARGS] = { NULL, NULL, NULL, NULL };
|
||||
int argc = tokenize(data, argv);
|
||||
|
||||
|
|
@ -101,6 +102,7 @@ static int parse(RzParse *p, const char *data, char *str) {
|
|||
for (i = 0; i < MAXARGS; i++) {
|
||||
free(argv[i]);
|
||||
}
|
||||
rz_strbuf_set(sb, str);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
182
librz/parse/p/parse_common.c
Normal file
182
librz/parse/p/parse_common.c
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
// SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
/** \file parse_common.c
|
||||
* This file contains a common code that can be used to convert any asm code
|
||||
* into a pseudo code, via a generic grammar.
|
||||
*
|
||||
* The grammar is quite simple; Let's take a simple example
|
||||
*
|
||||
* Let's take the following assembly
|
||||
* ; intel x86 asm
|
||||
* ; rax = rax + 10
|
||||
* add rax, 10
|
||||
*
|
||||
* The associated grammar will be "1 += 2" the number 1 will be changed to "rax" and 2 with "10"
|
||||
*
|
||||
* another example:
|
||||
*
|
||||
* ; mips asm
|
||||
* ; t0 = 4097 << 16
|
||||
* lui t0, 4097
|
||||
*
|
||||
* The associated grammar will be "1 = 2 << #16" to notice the `#` symbol.
|
||||
* The `#` symbol is used to ignore any set of chars after this till next whitespace/end of the line
|
||||
*
|
||||
* the developer has to provide a tokenize method to split the assembly in various token strings
|
||||
* and
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const char *mnemonic;
|
||||
size_t mnemonic_length;
|
||||
const char *grammar;
|
||||
} RzPseudoGrammar;
|
||||
|
||||
typedef struct {
|
||||
const char *expected;
|
||||
const char *pseudo;
|
||||
} RzPseudoDirect;
|
||||
|
||||
typedef struct {
|
||||
const char *expected;
|
||||
const char *replace;
|
||||
int flag; // 0 for first match, 1 for all matches
|
||||
} RzPseudoReplace;
|
||||
|
||||
typedef struct {
|
||||
const RzPseudoDirect *direct;
|
||||
size_t direct_length;
|
||||
const RzPseudoReplace *replace;
|
||||
size_t replace_length;
|
||||
const RzPseudoGrammar *lexicon;
|
||||
size_t lexicon_length;
|
||||
int max_args;
|
||||
RzList *(*tokenize)(const char *assembly, size_t length);
|
||||
} RzPseudoConfig;
|
||||
|
||||
#define RZ_PSEUDO_DEFINE_GRAMMAR(x, y) \
|
||||
{ .mnemonic = x, .mnemonic_length = sizeof(x) - 1, .grammar = y }
|
||||
|
||||
#define RZ_PSEUDO_DEFINE_DIRECT(x, y) \
|
||||
{ .expected = x, .pseudo = y }
|
||||
|
||||
#define RZ_PSEUDO_DEFINE_REPLACE(x, y, f) \
|
||||
{ .expected = x, .replace = y, .flag = f }
|
||||
|
||||
#define RZ_PSEUDO_DEFINE_CONFIG(d, l, r, m, t) \
|
||||
{ \
|
||||
.direct = d, \
|
||||
.direct_length = RZ_ARRAY_SIZE(d), \
|
||||
.replace = r, \
|
||||
.replace_length = RZ_ARRAY_SIZE(r), \
|
||||
.lexicon = l, \
|
||||
.lexicon_length = RZ_ARRAY_SIZE(l), \
|
||||
.max_args = m, \
|
||||
.tokenize = t, \
|
||||
}
|
||||
|
||||
#define RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(l, r, m, t) \
|
||||
{ \
|
||||
.direct = NULL, \
|
||||
.direct_length = 0, \
|
||||
.replace = r, \
|
||||
.replace_length = RZ_ARRAY_SIZE(r), \
|
||||
.lexicon = l, \
|
||||
.lexicon_length = RZ_ARRAY_SIZE(l), \
|
||||
.max_args = m, \
|
||||
.tokenize = t, \
|
||||
}
|
||||
|
||||
#define RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(l, m, t) \
|
||||
{ \
|
||||
.direct = NULL, \
|
||||
.direct_length = 0, \
|
||||
.replace = NULL, \
|
||||
.replace_length = 0, \
|
||||
.lexicon = l, \
|
||||
.lexicon_length = RZ_ARRAY_SIZE(l), \
|
||||
.max_args = m, \
|
||||
.tokenize = t, \
|
||||
}
|
||||
|
||||
static bool rz_pseudo_convert(const RzPseudoConfig *config, const char *assembly, RzStrBuf *sb) {
|
||||
rz_return_val_if_fail(config && config->tokenize && config->lexicon, false);
|
||||
|
||||
size_t i, p;
|
||||
const char *tmp = NULL;
|
||||
const RzPseudoGrammar *gr = NULL;
|
||||
const RzPseudoReplace *rp = NULL;
|
||||
|
||||
if (!strcmp(assembly, "invalid")) {
|
||||
return true;
|
||||
} else if (!strncmp(assembly, "trunc", 5)) {
|
||||
return true;
|
||||
} else if (!strcmp(assembly, "nop")) {
|
||||
return true;
|
||||
}
|
||||
size_t length = strlen(assembly);
|
||||
|
||||
for (i = 0; i < config->direct_length; ++i) {
|
||||
tmp = config->direct[i].expected;
|
||||
if (!strcmp(assembly, tmp)) {
|
||||
rz_strbuf_set(sb, config->direct[i].pseudo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
size_t mnemonic_length = length;
|
||||
if ((tmp = strchr(assembly, ' '))) {
|
||||
mnemonic_length = tmp - assembly;
|
||||
}
|
||||
for (i = 0; i < config->lexicon_length; ++i) {
|
||||
gr = &config->lexicon[i];
|
||||
if (gr->mnemonic_length == mnemonic_length && !strncmp(gr->mnemonic, assembly, mnemonic_length)) {
|
||||
break;
|
||||
}
|
||||
gr = NULL;
|
||||
}
|
||||
if (!gr) {
|
||||
rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
|
||||
return true;
|
||||
}
|
||||
|
||||
RzList *tokens = config->tokenize(assembly, length);
|
||||
if (!tokens) {
|
||||
rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0, p = 0; gr->grammar[p]; ++p) {
|
||||
int index = gr->grammar[p] - '0';
|
||||
if (index > 0 && index < config->max_args) {
|
||||
tmp = (const char *)rz_list_get_n(tokens, index);
|
||||
if (!tmp) {
|
||||
tmp = "?";
|
||||
}
|
||||
rz_strbuf_append_n(sb, gr->grammar + i, p - i);
|
||||
i = p + 1;
|
||||
rz_strbuf_append(sb, tmp);
|
||||
} else if (gr->grammar[p] == '#') {
|
||||
rz_strbuf_append_n(sb, gr->grammar + i, p - i);
|
||||
i = p + 1;
|
||||
p++;
|
||||
while (gr->grammar[p] && !IS_WHITESPACE(gr->grammar[p])) {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i < p) {
|
||||
rz_strbuf_append_n(sb, gr->grammar + i, p - i);
|
||||
}
|
||||
|
||||
char *result = rz_strbuf_get(sb);
|
||||
for (int i = 0; i < config->replace_length; ++i) {
|
||||
rp = &config->replace[i];
|
||||
rz_str_replace(result, rp->expected, rp->replace, rp->flag);
|
||||
}
|
||||
|
||||
rz_list_free(tokens);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2012-2017 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -11,350 +11,249 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ "rsub-int", "1 = 2 - 3" },
|
||||
{ "float-to-double", "1 = (double)(float) 2" },
|
||||
{ "float-to-long", "1 = (long)(float) 2" },
|
||||
{ "float-to-int", "1 = (int)(float) 2" },
|
||||
{ "long-to-float", "1 = (float)(long) 2" },
|
||||
{ "long-to-int", "1 = (int)(long) 2" },
|
||||
{ "long-to-double", "1 = (double) 2" },
|
||||
{ "double-to-long", "1 = (long) 2" },
|
||||
{ "double-to-int", "1 = (int) 2" },
|
||||
{ "int-to-double", "1 = (double) 2" },
|
||||
{ "int-to-long", "1 = (long) 2" },
|
||||
{ "int-to-byte", "1 = (byte) 2" },
|
||||
{ "aget-byte", "1 = (byte) 2[3]" },
|
||||
{ "aget-short", "1 = (short) 2[3]" },
|
||||
{ "aget-object", "1 = (object) 2[3]" },
|
||||
{ "sput-wide", "1 = 2" },
|
||||
{ "sput-object", "1 = 2" },
|
||||
{ "add-long", "1 = 2 + 3" },
|
||||
{ "add-double", "1 = 2 + 3" },
|
||||
{ "mul-long", "1 = 2 * 3" },
|
||||
{ "const-string/jumbo", "1 = (jumbo-string) 2" },
|
||||
{ "const-string", "1 = (string) 2" },
|
||||
{ "const-wide", "1 = (wide) 2" },
|
||||
{ "const/4", "1 = (wide) 2" },
|
||||
{ "cmp-int", "1 = (2 == 3)" },
|
||||
{ "cmp-long", "1 = (2 == 3)" },
|
||||
{ "cmpl-double", "1 = (double)(2 == 3)" },
|
||||
{ "cmpl-float", "1 = (float)(2 == 3)" },
|
||||
{ "cmpl-int", "1 = (int)(2 == 3)" },
|
||||
{ "cmpg-double", "1 = (2 == 3)" },
|
||||
{ "cmpg-float", "1 = (2 == 3)" },
|
||||
{ "or-int/2addr", "1 |= 2" },
|
||||
{ "or-long", "1 |= 2" },
|
||||
{ "and-long/2addr", "1 &= (long) 2" },
|
||||
{ "and-int", "1 &= (int) 2" },
|
||||
{ "and-byte", "1 &= (byte) 2" },
|
||||
{ "sub-float/2addr", "1 -= 2" },
|
||||
{ "sub-float", "1 = 2 - 3" },
|
||||
{ "sub-int", "1 = (int) 2 - 3" },
|
||||
{ "sub-long", "1 = (long) 2 - 3" },
|
||||
{ "sub-long/2addr", "1 -= (long) 2" },
|
||||
{ "sub-int/2addr", "1 -= 2" },
|
||||
{ "move", "1 = 2" },
|
||||
{ "move/16", "1 = 2" },
|
||||
{ "move-object", "1 = (object) 2" },
|
||||
{ "move-object/16", "1 = (object) 2" },
|
||||
{ "move-object/from16", "1 = (object) 2" },
|
||||
{ "move-wide/from16", "1 = (wide) 2" },
|
||||
{ "array-length", "1 = Array.length (2)" },
|
||||
{ "new-array", "1 = new array (2, 3)" },
|
||||
{ "new-instance", "1 = new 2" },
|
||||
{ "shr-long/2addr", "1 >>= 2" },
|
||||
{ "shr-long", "1 = (long) 2 >> 3" },
|
||||
{ "shr-int", "1 = (int) 2 >> 3" },
|
||||
{ "ushr-int", "1 = (int) 2 >>> 3" },
|
||||
{ "ushr-int/2addr", "1 >>>= 2" },
|
||||
{ "ushr-long", "1 = (long) 2 >>> 3" },
|
||||
{ "ushl-int/2addr", "1 <<<= 2" },
|
||||
{ "shl-int/2addr", "1 <<<= 2" },
|
||||
{ "shl-int", "1 = (int) 2 << 3" },
|
||||
{ "shl-long", "1 = (long) 2 << 3" },
|
||||
{ "move/from16", "1 = 2" },
|
||||
{ "move-exception", "1 = exception" },
|
||||
{ "move-result", "1 = result" },
|
||||
{ "move-result-wide", "1 = (wide) result" },
|
||||
{ "move-result-object", "1 = (object) result" },
|
||||
{ "const-wide/high16", "1 = 2" },
|
||||
{ "const/16", "1 = 2" },
|
||||
{ "const-wide/16", "1 = 2" },
|
||||
{ "const-wide/32", "1 = 2" },
|
||||
{ "const-class", "1 = (class) 2" },
|
||||
{ "const/high16", "1 = 2" },
|
||||
{ "const", "1 = 2" },
|
||||
{ "rem-long", "1 = (long) 2 % 3" },
|
||||
{ "rem-double", "1 = (double) 2 % 3" },
|
||||
{ "rem-float", "1 = (float) 2 % 3" },
|
||||
{ "rem-long/2addr", "1 %= 2" },
|
||||
{ "rem-float/2addr", "1 %= (float) 2" },
|
||||
{ "rem-double/2addr", "1 %= (double) 2" },
|
||||
{ "instance-of", "1 = insteanceof (2) == 3" },
|
||||
{ "aput", "2[3] = 1" },
|
||||
{ "aput-byte", "2[3] = (byte) 1" },
|
||||
{ "aput-short", "2[3] = (short) 1" },
|
||||
{ "aput-object", "2[3] = (object) 1" },
|
||||
{ "aput-wide", "2[3] = (wide) 1" },
|
||||
{ "aput-char", "2[3] = (char) 1" },
|
||||
{ "aput-boolean", "2[3] = (bool) 1" },
|
||||
{ "aget", "1 = 2[3]" },
|
||||
{ "aget-wide", "1 = (wide) 2[3]" },
|
||||
{ "aget-char", "1 = (char) 2[3]" },
|
||||
{ "aget-boolean", "1 = (boolean) 2[3]" },
|
||||
{ "sget", "1 = 2" },
|
||||
{ "sget-char", "1 = (char) 2" },
|
||||
{ "sget-short", "1 = (short) 2" },
|
||||
{ "sget-boolean", "1 = (bool) 2" },
|
||||
{ "sget-object", "1 = (object) 2" },
|
||||
{ "iput", "2[3] = 1" },
|
||||
{ "iput-object", "2[3] = (object) 1" },
|
||||
{ "iput-byte", "2[3] = (byte) 1" },
|
||||
{ "iput-char", "2[3] = (char) 1" },
|
||||
{ "iput-boolean", "2[3] = (bool) 1" },
|
||||
{ "sput-boolean", "2[3] = (bool) 1" },
|
||||
{ "sput-char", "2[3] = (char) 1" },
|
||||
{ "iput-int", "2[3] = (int) 1" },
|
||||
{ "iget", "1 = 2[3]" },
|
||||
{ "sget-byte", "1 = (byte) 2 [3]" },
|
||||
{ "iget-byte", "1 = (byte) 2 [3]" },
|
||||
{ "iget-char", "1 = (char) 2 [3]" },
|
||||
{ "iget-short", "1 = (short) 2 [3]" },
|
||||
{ "iget-wide", "1 = (wide) 2 [3]" },
|
||||
{ "iget-object", "1 = (2) 3" },
|
||||
{ "iget-boolean", "1 = (bool) 2 [3]" },
|
||||
{ "+iget-wide-volatile", "1 = (wide-volatile) 2 [3]" },
|
||||
{ "if-eq", "if (1 == 2) goto 3" },
|
||||
{ "if-lt", "if (1 < 2) goto 3" },
|
||||
{ "if-ne", "if (1 != 2) goto 3" },
|
||||
{ "if-eqz", "if (!1) goto 2" },
|
||||
{ "if-ge", "if (1 > zero) goto 2" },
|
||||
{ "if-le", "if (1 <= 2) goto 3" },
|
||||
{ "if-gtz", "if (1 > 0) goto 2" },
|
||||
{ "filled-new-array", "1 = new Array(2)" },
|
||||
{ "neg-long", "1 = -2" },
|
||||
{ "neg-double", "1 = -2" },
|
||||
{ "neg-float", "1 = -2" },
|
||||
{ "not-int", "1 = !2" },
|
||||
{ "packed-switch", "switch 2" },
|
||||
{ "sparse-switch", "switch 2" },
|
||||
{ "invoke-direct", "call 2 1" },
|
||||
{ "invoke-direct/range", "call 2 1" },
|
||||
{ "invoke-interface", "call 2 1" },
|
||||
{ "invoke-static", "call 2 1" },
|
||||
{ "invoke-super", "call super 2 1" },
|
||||
{ "invoke-super/range", "call super 2 1" },
|
||||
{ "invoke-polymorphic", "call polymorphic 2 1" },
|
||||
{ "invoke-virtual/range", "call 2 1" },
|
||||
{ "invoke-virtual", "call 2 1" },
|
||||
{ "+invoke-virtual-quick", "call 2 1" },
|
||||
{ "+invoke-interface/range", "call 2 1" },
|
||||
{ "invoke-interface/range", "call 2 1" },
|
||||
{ "div-float/2addr", "1 /= (float) 2" },
|
||||
{ "div-double/2addr", "1 /= (double) 2" },
|
||||
{ "div-double", "1 = (double) 2 / 3" },
|
||||
{ "div-float", "1 = 2 / 3" },
|
||||
{ "div-int/lit8", "1 = 2 / 3" },
|
||||
{ "div-int/lit16", "1 = 2 / 3" },
|
||||
{ "div-int/2addr", "1 /= 2" },
|
||||
{ "div-int", "1 = (int)(2 / 3)" },
|
||||
{ "goto/16", "goto 1" },
|
||||
{ "goto/32", "goto 1" },
|
||||
{ "or-int", "1 = (int)(2 | 3)" },
|
||||
{ "xor-int", "1 = (int)(2 ^ 3)" },
|
||||
{ "xor-int/2addr", "1 ^= 2" },
|
||||
{ "xor-byte", "1 = (byte)(2 ^ 3)" },
|
||||
{ "xor-short", "1 = (short)(2 ^ 3)" },
|
||||
{ "sub-int", "1 = (int)(2 - 3)" },
|
||||
{ "if-nez", "if (1) goto 2" },
|
||||
{ "if-ltz", "if (1 <=) goto 2" },
|
||||
{ "mul-int", "1 = (int)(2 * 3)" },
|
||||
{ "mul-int/lit8", "1 = (2 * 3)" },
|
||||
{ "check-cast", "if (1 instanceof 2)" },
|
||||
{ "add-int", "1 = (int)(2 + 3)" },
|
||||
{ "add-int/lit8", "1 = 2 + 3" },
|
||||
{ "add-int/lit16", "1 = 2 + 3" },
|
||||
{ "add-int/2addr", "1 += 2" },
|
||||
{ "add-double", "1 = (double)(2 + 3)" },
|
||||
{ "add-double/2addr", "1 += (double)2" },
|
||||
{ "mul-float/2addr", "1 *= 2" },
|
||||
{ "mul-float", "1 = 2 * 3" },
|
||||
{ "xor-long", "1 = (long)(2 ^ 3)" },
|
||||
{ "mul-double", "1 = 2 * 3" },
|
||||
{ "move-wide", "1 = 2" },
|
||||
{ "move-wide/16", "1 = 2" },
|
||||
{ "return-wide", "return (wide) 1" },
|
||||
{ "return-object", "return (object) 1" },
|
||||
// { "sget", "1 = 2[3]"},
|
||||
{ NULL }
|
||||
};
|
||||
#include "parse_common.c"
|
||||
|
||||
for (i = 0; ops[i].op != NULL; i++) {
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
if (newstr != NULL) {
|
||||
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
|
||||
if (ops[i].str[j] >= '1' && ops[i].str[j] <= '9') {
|
||||
const char *w = argv[ops[i].str[j] - '0'];
|
||||
if (w != NULL) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
static RzList *dalvik_tokenize(const char *assembly, size_t length);
|
||||
|
||||
static const RzPseudoGrammar dalvik_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("+iget-wide-volatile", "1 = (wide-volatile) 2 [3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("+invoke-interface/range", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("+invoke-virtual-quick", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-double", "1 = (double)(2 + 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-double", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-double/2addr", "1 += (double)2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-int", "1 = (int)(2 + 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-int/2addr", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-int/lit16", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-int/lit8", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add-long", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aget", "1 = 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aget-boolean", "1 = (boolean) 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aget-byte", "1 = (byte) 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aget-char", "1 = (char) 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aget-object", "1 = (object) 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aget-short", "1 = (short) 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aget-wide", "1 = (wide) 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and-byte", "1 &= (byte) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and-int", "1 &= (int) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and-long/2addr", "1 &= (long) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aput", "2[3] = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aput-boolean", "2[3] = (bool) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aput-byte", "2[3] = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aput-char", "2[3] = (char) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aput-object", "2[3] = (object) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aput-short", "2[3] = (short) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("aput-wide", "2[3] = (wide) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("array-length", "1 = Array.length (2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("check-cast", "if (1 instanceof 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp-int", "1 = (2 == 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp-long", "1 = (2 == 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpg-double", "1 = (2 == 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpg-float", "1 = (2 == 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpl-double", "1 = (double)(2 == 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpl-float", "1 = (float)(2 == 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpl-int", "1 = (int)(2 == 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const-class", "1 = (class) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const-string", "1 = (string) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const-string/jumbo", "1 = (jumbo-string) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide", "1 = (wide) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide/16", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide/32", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide/high16", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const/16", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const/4", "1 = (wide) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("const/high16", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-double", "1 = (double) 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-double/2addr", "1 /= (double) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-float", "1 = 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-float/2addr", "1 /= (float) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-int", "1 = (int)(2 / 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-int/2addr", "1 /= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-int/lit16", "1 = 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div-int/lit8", "1 = 2 / 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("double-to-int", "1 = (int) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("double-to-long", "1 = (long) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("filled-new-array", "1 = new Array(2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("float-to-double", "1 = (double)(float) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("float-to-int", "1 = (int)(float) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("float-to-long", "1 = (long)(float) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("goto/16", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("goto/32", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-eq", "if (1 == 2) goto 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-eqz", "if (!1) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-ge", "if (1 > zero) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-gtz", "if (1 > 0) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-le", "if (1 <= 2) goto 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-lt", "if (1 < 2) goto 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-ltz", "if (1 <=) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-ne", "if (1 != 2) goto 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("if-nez", "if (1) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iget", "1 = 2[3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iget-boolean", "1 = (bool) 2 [3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iget-byte", "1 = (byte) 2 [3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iget-char", "1 = (char) 2 [3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iget-object", "1 = (2) 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iget-short", "1 = (short) 2 [3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iget-wide", "1 = (wide) 2 [3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("instance-of", "1 = insteanceof (2) == 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("int-to-byte", "1 = (byte) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("int-to-double", "1 = (double) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("int-to-long", "1 = (long) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-direct", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-direct/range", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-interface", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-interface/range", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-polymorphic", "call polymorphic 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-static", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-super", "call super 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-super/range", "call super 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-virtual", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-virtual/range", "call 2 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iput", "2[3] = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iput-boolean", "2[3] = (bool) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iput-byte", "2[3] = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iput-char", "2[3] = (char) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iput-int", "2[3] = (int) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("iput-object", "2[3] = (object) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("long-to-double", "1 = (double) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("long-to-float", "1 = (float)(long) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("long-to-int", "1 = (int)(long) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-exception", "1 = exception"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-object", "1 = (object) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-object/16", "1 = (object) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-object/from16", "1 = (object) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-result", "1 = result"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-result-object", "1 = (object) result"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-result-wide", "1 = (wide) result"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-wide", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-wide/16", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move-wide/from16", "1 = (wide) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move/16", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move/from16", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul-double", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul-float", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul-float/2addr", "1 *= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul-int", "1 = (int)(2 * 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul-int/lit8", "1 = (2 * 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul-long", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("neg-double", "1 = -2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("neg-float", "1 = -2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("neg-long", "1 = -2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("new-array", "1 = new array (2, 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("new-instance", "1 = 2.new"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("not-int", "1 = !2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or-int", "1 = (int)(2 | 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or-int/2addr", "1 |= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or-long", "1 |= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("packed-switch", "switch 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rem-double", "1 = (double) 2 % 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rem-double/2addr", "1 %= (double) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rem-float", "1 = (float) 2 % 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rem-float/2addr", "1 %= (float) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rem-long", "1 = (long) 2 % 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rem-long/2addr", "1 %= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("return-object", "return (object) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("return-void", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("return-wide", "return (wide) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rsub-int", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sget", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sget-boolean", "1 = (bool) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sget-byte", "1 = (byte) 2 [3]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sget-char", "1 = (char) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sget-object", "1 = (object) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sget-short", "1 = (short) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shl-int", "1 = (int) 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shl-int/2addr", "1 <<<= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shl-long", "1 = (long) 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shr-int", "1 = (int) 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shr-long", "1 = (long) 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shr-long/2addr", "1 >>= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sparse-switch", "switch 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sput", "1 = 2 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sput-boolean", "2[3] = (bool) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sput-char", "2[3] = (char) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sput-object", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sput-wide", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub-float", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub-float/2addr", "1 -= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub-int", "1 = (int) 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub-int", "1 = (int)(2 - 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub-int/2addr", "1 -= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub-long", "1 = (long) 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub-long/2addr", "1 -= (long) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ushl-int/2addr", "1 <<<= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ushr-int", "1 = (int) 2 >>> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ushr-int/2addr", "1 >>>= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ushr-long", "1 = (long) 2 >>> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor-byte", "1 = (byte)(2 ^ 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor-int", "1 = (int)(2 ^ 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor-int/2addr", "1 ^= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor-long", "1 = (long)(2 ^ 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor-short", "1 = (short)(2 ^ 3)"),
|
||||
};
|
||||
|
||||
static const RzPseudoReplace dalvik_replace[] = {
|
||||
RZ_PSEUDO_DEFINE_REPLACE("{", "(", 1),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("}", ")", 1),
|
||||
RZ_PSEUDO_DEFINE_REPLACE(";", "", 1),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig dalvik_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(dalvik_lexicon, dalvik_replace, 4, dalvik_tokenize);
|
||||
|
||||
RzList *dalvik_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
RzList *tokens = NULL;
|
||||
const char *comma_replace = NULL;
|
||||
bool keep = false;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
if (!keep) {
|
||||
p++;
|
||||
} else if (buf[p + 1] == ' ') {
|
||||
buf[i] = buf[p];
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
} else if (buf[p] == '{') {
|
||||
keep = true;
|
||||
comma_replace = ", ";
|
||||
} else if (buf[p] == '}') {
|
||||
keep = false;
|
||||
}
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (comma_replace) {
|
||||
RzListIter *it;
|
||||
rz_list_foreach (tokens, it, buf) {
|
||||
it->data = rz_str_replace(buf, ",", comma_replace, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: this is slow */
|
||||
if (newstr != NULL) {
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
int i, len = strlen(data);
|
||||
char *buf, *ptr, *optr, *ptr2;
|
||||
char w0[64];
|
||||
char w1[64];
|
||||
char w2[64];
|
||||
char w3[64];
|
||||
char w4[64];
|
||||
|
||||
if (!strcmp(data, "invalid") || !strcmp(data, "nop") || !strcmp(data, "DEPRECATED")) {
|
||||
str[0] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// malloc can be slow here :?
|
||||
if (!(buf = malloc(len + 1))) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf, data, len + 1);
|
||||
|
||||
rz_str_trim(buf);
|
||||
|
||||
if (*buf) {
|
||||
w0[0] = '\0';
|
||||
w1[0] = '\0';
|
||||
w2[0] = '\0';
|
||||
w3[0] = '\0';
|
||||
w4[0] = '\0';
|
||||
ptr = strchr(buf, ' ');
|
||||
if (!ptr) {
|
||||
ptr = strchr(buf, '\t');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w0, buf, sizeof(w0) - 1);
|
||||
w0[sizeof(w0) - 1] = '\0';
|
||||
strncpy(w1, ptr, sizeof(w1) - 1);
|
||||
w1[sizeof(w1) - 1] = '\0';
|
||||
|
||||
optr = ptr;
|
||||
ptr2 = strchr(ptr, '}');
|
||||
if (ptr2) {
|
||||
ptr = ptr2 + 1;
|
||||
}
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w1, optr, sizeof(w1) - 1);
|
||||
w1[sizeof(w1) - 1] = '\0';
|
||||
strncpy(w2, ptr, sizeof(w2) - 1);
|
||||
w2[sizeof(w2) - 1] = '\0';
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w2, optr, sizeof(w2) - 1);
|
||||
w2[sizeof(w2) - 1] = '\0';
|
||||
strncpy(w3, ptr, sizeof(w3) - 1);
|
||||
w3[sizeof(w3) - 1] = '\0';
|
||||
optr = ptr;
|
||||
// bonus
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w3, optr, sizeof(w3) - 1);
|
||||
w3[sizeof(w3) - 1] = '\0';
|
||||
strncpy(w4, ptr, sizeof(w4) - 1);
|
||||
w4[sizeof(w4) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const char *wa[] = { w0, w1, w2, w3, w4 };
|
||||
int nw = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (wa[i][0] != '\0') {
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str);
|
||||
{
|
||||
char *p = strdup(str);
|
||||
p = rz_str_replace(p, "+ -", "- ", 0);
|
||||
#if EXPERIMENTAL_ZERO
|
||||
p = rz_str_replace(p, "zero", "0", 0);
|
||||
if (!memcmp(p, "0 = ", 4))
|
||||
*p = 0; // nop
|
||||
#endif
|
||||
if (!strcmp(w1, w2)) {
|
||||
char a[32], b[32];
|
||||
#define REPLACE(x, y) \
|
||||
do { \
|
||||
int snprintf_len1_ = snprintf(a, 32, x, w1, w1); \
|
||||
int snprintf_len2_ = snprintf(b, 32, y, w1); \
|
||||
if (snprintf_len1_ < 32 && snprintf_len2_ < 32) { \
|
||||
p = rz_str_replace(p, a, b, 0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// TODO: optimize
|
||||
REPLACE("%s = %s +", "%s +=");
|
||||
REPLACE("%s = %s -", "%s -=");
|
||||
REPLACE("%s = %s &", "%s &=");
|
||||
REPLACE("%s = %s |", "%s |=");
|
||||
REPLACE("%s = %s ^", "%s ^=");
|
||||
REPLACE("%s = %s >>", "%s >>=");
|
||||
REPLACE("%s = %s <<", "%s <<=");
|
||||
}
|
||||
strcpy(str, p);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return true;
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&dalvik_config, assembly, sb);
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_dalvik_pseudo = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2016 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -11,190 +11,92 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
static bool can_replace(const char *str, int idx, int max_operands) {
|
||||
if (str[idx] > '9' || str[idx] < '1') {
|
||||
return false;
|
||||
}
|
||||
if (str[idx + 1] != '\x00' && str[idx + 1] <= '9' && str[idx + 1] >= '1') {
|
||||
return false;
|
||||
}
|
||||
if ((int)((int)str[idx] - 0x30) > max_operands) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#include "parse_common.c"
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
char *op;
|
||||
char *str;
|
||||
int max_operands;
|
||||
} ops[] = {
|
||||
{ "move", "2 = 1", 2 },
|
||||
{ "movea", "2 = 1", 2 },
|
||||
{ "moveq", "2 = 1", 2 },
|
||||
{ "movem", "2 = 1", 2 },
|
||||
{ "lea", "2 = 1", 2 },
|
||||
{ "bsr", "1()", 1 },
|
||||
{ "jsr", "1()", 1 },
|
||||
{ "beq", "if (==) jmp 1", 1 },
|
||||
{ "blt", "if (<) jmp 1", 1 },
|
||||
{ "ble", "if (<=) jmp 1", 1 },
|
||||
{ "bgt", "if (>) jmp 1", 1 },
|
||||
{ "bge", "if (>=) jmp 1", 1 },
|
||||
{ "bcs", "if (cs) jmp 1", 1 },
|
||||
{ "bcc", "if (cc) jmp 1", 1 },
|
||||
{ "bra", "jmp 1", 1 },
|
||||
{ "jmp", "jmp 1", 1 },
|
||||
{ "rts", "ret", 2 },
|
||||
{ "btst", "1 == 2", 2 },
|
||||
{ "cmp", "1 == 2", 2 },
|
||||
{ "cmpi", "2 == 1", 2 },
|
||||
{ "add", "1 += 2", 2 },
|
||||
{ "addi", "1 += 2", 2 },
|
||||
{ "adda", "1 += 2", 2 },
|
||||
{ "sub", "1 += 2", 2 },
|
||||
{ "subq", "1 += 2", 2 },
|
||||
{ "tst", "1 == 2", 2 },
|
||||
{ "ori", "2 |= 1", 2 },
|
||||
{ "or", "2 |= 1", 2 },
|
||||
{ "lsr", "2 >>= 1", 2 },
|
||||
{ "lsl", "2 <<= 1", 2 },
|
||||
{ "andi", "2 &= 1", 2 },
|
||||
{ "nop", "" },
|
||||
//
|
||||
{ NULL }
|
||||
};
|
||||
static RzList *m68k_tokenize(const char *assembly, size_t length);
|
||||
|
||||
for (i = 0; ops[i].op != NULL; i++) {
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
if (newstr != NULL) {
|
||||
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
|
||||
if (can_replace(ops[i].str, j, ops[i].max_operands)) {
|
||||
const char *w = argv[ops[i].str[j] - '0'];
|
||||
if (w != NULL) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
}
|
||||
return true;
|
||||
static const RzPseudoGrammar m68k_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adda", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addi", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addq", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "2 &= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bcc", "if (cc) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bcs", "if (cs) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bne", "if (!=) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (==) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bge", "if (>=) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bgt", "if (>) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ble", "if (<=) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("blt", "if (<) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bra", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bsr", "call 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("btst", "1 == 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "1 == 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpi", "2 == 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jsr", "call 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lea", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsl", "2 <<= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lsr", "2 >>= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movea", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movem", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("moveq", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or", "2 |= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "2 |= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rts", "ret"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subq", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "1 == 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clr", "1 = 0"),
|
||||
};
|
||||
|
||||
static const RzPseudoReplace m68k_replace[] = {
|
||||
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig m68k_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(m68k_lexicon, m68k_replace, 4, m68k_tokenize);
|
||||
|
||||
RzList *m68k_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
p++;
|
||||
}
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
/* TODO: this is slow */
|
||||
if (newstr != NULL) {
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
#define WSZ 64
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
int i, len = strlen(data);
|
||||
char w0[WSZ];
|
||||
char w1[WSZ];
|
||||
char w2[WSZ];
|
||||
char w3[WSZ];
|
||||
char w4[WSZ];
|
||||
char *buf, *ptr, *optr;
|
||||
|
||||
if (!strcmp(data, "jr ra")) {
|
||||
strcpy(str, "ret");
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
char *copy = strdup(assembly);
|
||||
if (!copy) {
|
||||
rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
|
||||
return true;
|
||||
}
|
||||
|
||||
// malloc can be slow here :?
|
||||
if (!(buf = malloc(len + 1))) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf, data, len + 1);
|
||||
|
||||
rz_str_replace_in(buf, len + 1, ".l", "", 1);
|
||||
rz_str_replace_in(buf, len + 1, ".w", "", 1);
|
||||
rz_str_replace_in(buf, len + 1, ".d", "", 1);
|
||||
rz_str_replace_in(buf, len + 1, ".b", "", 1);
|
||||
rz_str_trim(buf);
|
||||
|
||||
if (*buf) {
|
||||
w0[0] = '\0';
|
||||
w1[0] = '\0';
|
||||
w2[0] = '\0';
|
||||
w3[0] = '\0';
|
||||
w4[0] = '\0';
|
||||
ptr = strchr(buf, ' ');
|
||||
if (!ptr) {
|
||||
ptr = strchr(buf, '\t');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w0, buf, WSZ - 1);
|
||||
strncpy(w1, ptr, WSZ - 1);
|
||||
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w1, optr, WSZ - 1);
|
||||
strncpy(w2, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w2, optr, WSZ - 1);
|
||||
strncpy(w3, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
// bonus
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w3, optr, WSZ - 1);
|
||||
strncpy(w4, ptr, WSZ - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const char *wa[] = { w0, w1, w2, w3, w4 };
|
||||
int nw = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (wa[i][0] != '\0') {
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str);
|
||||
{
|
||||
char *pluseq = strstr(str, "+ =");
|
||||
if (pluseq) {
|
||||
memcpy(pluseq, " +=", 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return true;
|
||||
rz_str_replace(copy, ".l", "", 0);
|
||||
rz_str_replace(copy, ".w", "", 0);
|
||||
rz_str_replace(copy, ".d", "", 0);
|
||||
rz_str_replace(copy, ".b", "", 0);
|
||||
bool res = rz_pseudo_convert(&m68k_config, copy, sb);
|
||||
free(copy);
|
||||
return res;
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_m68k_pseudo = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2012-2017 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -11,245 +12,133 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
static int can_replace(const char *str, int idx, int max_operands) {
|
||||
if (str[idx] > '9' || str[idx] < '1') {
|
||||
return false;
|
||||
}
|
||||
if (str[idx + 1] != '\x00' && str[idx + 1] <= '9' && str[idx + 1] >= '1') {
|
||||
return false;
|
||||
}
|
||||
if ((int)((int)str[idx] - 0x30) > max_operands) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#include "parse_common.c"
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
char *op;
|
||||
char *str;
|
||||
int max_operands;
|
||||
} ops[] = {
|
||||
{ "add", "1 = 2 + 3", 3 },
|
||||
{ "addi", "1 = 2 + 3", 3 },
|
||||
{ "addiu", "1 = 2 + 3", 3 },
|
||||
{ "addu", "1 = 2 + 3", 3 },
|
||||
{ "and", "1 = 2 & 3", 3 },
|
||||
{ "andi", "1 = 2 & 3", 3 },
|
||||
{ "b", "goto 1", 1 },
|
||||
{ "bal", "call 1", 1 },
|
||||
{ "begzal", "if (1 >= 0) call 2", 2 },
|
||||
{ "beq", "if (1 == 2) goto 3", 3 },
|
||||
{ "beqz", "if (!1) goto 2", 2 },
|
||||
{ "bgez", "if (1 >= 0) goto 2", 2 },
|
||||
{ "bgtz", "if (1 > 0) goto 2", 2 },
|
||||
{ "blez", "if (1 <= 0) goto 2", 2 },
|
||||
{ "bltz", "if (1 < 0) goto 2", 2 },
|
||||
{ "bltzal", "if (1 < 0) call 2", 2 },
|
||||
{ "bne", "if (1 != 2) goto 3", 3 },
|
||||
{ "bnez", "if (1) goto 2", 2 },
|
||||
{ "j", "goto 1", 1 },
|
||||
{ "jal", "call 1", 1 },
|
||||
{ "jalr", "call 1", 1 },
|
||||
{ "jr", "goto 1", 1 },
|
||||
{ "lb", "1 = byte [3 + 2]", 3 },
|
||||
{ "lbu", "1 = (unsigned) byte [3 + 2]", 3 },
|
||||
{ "lh", "1 = halfword [3 + 2]", 3 },
|
||||
{ "lhu", "1 = (unsigned) halfword [3 + 2]", 3 },
|
||||
{ "li", "1 = 2", 2 },
|
||||
{ "lui", "1 = 2 << 16", 2 },
|
||||
{ "lw", "1 = [3 + 2]", 3 },
|
||||
{ "mfhi", "1 = hi", 1 },
|
||||
{ "mflo", "1 = lo", 1 },
|
||||
{ "move", "1 = 2", 2 },
|
||||
{ "movn", "if (3) 1 = 2", 3 },
|
||||
{ "movz", "if (!3) 1 = 2", 3 },
|
||||
{ "mult", "(hi,lo) = 1 * 2", 2 },
|
||||
{ "multu", "unsigned (hi,lo) = 1 * 2", 2 },
|
||||
{ "mul", "1 = 2 * 3", 3 },
|
||||
{ "mulu", "1 = 2 * 3", 3 },
|
||||
{ "negu", "1 = ~2", 2 },
|
||||
{ "nop", "", 0 },
|
||||
{ "nor", "1 = ~(2 | 3)", 3 },
|
||||
{ "or", "1 = 2 | 3", 3 },
|
||||
{ "ori", "1 = 2 | 3", 3 },
|
||||
{ "sb", "byte [3 + 2] = 1", 3 },
|
||||
{ "sh", "halfword [3 + 2] = 1", 3 },
|
||||
{ "sll", "1 = 2 << 3", 3 },
|
||||
{ "sllv", "1 = 2 << 3", 3 },
|
||||
{ "slr", "1 = 2 >> 3", 3 }, // logic
|
||||
{ "slt", "1 = (2 < 3)", 3 },
|
||||
{ "slti", "1 = (2 < 3)", 3 },
|
||||
{ "sltiu", "1 = (unsigned) (2 < 3)", 3 },
|
||||
{ "sltu", "1 = (unsigned) (2 < 3)", 3 },
|
||||
{ "sra", "1 = (signed) 2 >> 3", 3 }, // arithmetic
|
||||
{ "srl", "1 = 2 >> 3", 3 },
|
||||
{ "srlv", "1 = 2 >> 3", 3 },
|
||||
{ "subu", "1 = 2 - 3", 3 },
|
||||
{ "sub", "1 = 2 - 3", 3 },
|
||||
{ "sw", "[3 + 2] = 1", 3 },
|
||||
{ "syscall", "syscall", 0 },
|
||||
{ "xor", "1 = 2 ^ 3", 3 },
|
||||
{ "xori", "1 = 2 ^ 3", 3 },
|
||||
{ NULL }
|
||||
};
|
||||
static RzList *mips_tokenize(const char *assembly, size_t length);
|
||||
|
||||
for (i = 0; ops[i].op != NULL; i++) {
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
if (newstr != NULL) {
|
||||
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
|
||||
if (can_replace(ops[i].str, j, ops[i].max_operands)) {
|
||||
const char *w = argv[ops[i].str[j] - '0'];
|
||||
if (w != NULL) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
static const RzPseudoGrammar mips_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addi", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addiu", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addu", "1 = 2 + 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 = 2 & 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "1 = 2 & 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("b", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bal", "call 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("begzal", "if (1 >= 0) call 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (1 == 2) goto 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("beqz", "if (!1) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bgez", "if (1 >= 0) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bgtz", "if (1 > 0) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("blez", "if (1 <= 0) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bltz", "if (1 < 0) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bltzal", "if (1 < 0) call 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bne", "if (1 != 2) goto 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bnez", "if (1) goto 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("j", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jal", "call 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jalr", "call 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jr", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lb", "1 = byte [3 + 2]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lbu", "1 = (unsigned) byte [3 + 2]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lh", "1 = halfword [3 + 2]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lhu", "1 = (unsigned) halfword [3 + 2]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("li", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lui", "1 = 2 << #16"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lw", "1 = word [3 + 2]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mfhi", "1 = hi"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mflo", "1 = lo"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("move", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movn", "if (3) 1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movz", "if (!3) 1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mult", "(hi,lo) = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("multu", "unsigned (hi,lo) = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mulu", "1 = 2 * 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("negu", "1 = ~2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nor", "1 = ~(2 | 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or", "1 = 2 | 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "1 = 2 | 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sb", "byte [3 + 2] = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sh", "halfword [3 + 2] = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sll", "1 = 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sllv", "1 = 2 << 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("slr", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("slt", "1 = (2 < 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("slti", "1 = (2 < 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sltiu", "1 = (unsigned) (2 < 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sltu", "1 = (unsigned) (2 < 3)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sra", "1 = (signed) 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("srl", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("srlv", "1 = 2 >> 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subu", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 = 2 - 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sw", "word [3 + 2] = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("syscall", "syscall"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "1 = 2 ^ 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xori", "1 = 2 ^ 3"),
|
||||
};
|
||||
|
||||
static const RzPseudoDirect mips_direct[] = {
|
||||
RZ_PSEUDO_DEFINE_DIRECT("jr ra", "return"),
|
||||
};
|
||||
|
||||
static const RzPseudoReplace mips_replace[] = {
|
||||
RZ_PSEUDO_DEFINE_REPLACE(" + 0]", "]", 0),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("0 << 16", "0", 1),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig mips_config = RZ_PSEUDO_DEFINE_CONFIG(mips_direct, mips_lexicon, mips_replace, 4, mips_tokenize);
|
||||
|
||||
RzList *mips_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
bool insert_zero = false;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
p++;
|
||||
} else if (buf[p] == '(') {
|
||||
buf[p] = ' ';
|
||||
if (!IS_HEXCHAR(buf[p - 1])) {
|
||||
p++;
|
||||
insert_zero = true;
|
||||
}
|
||||
return true;
|
||||
} else if (buf[p] == ')') {
|
||||
buf[p] = 0;
|
||||
} else if (buf[p] == 'z' && buf[p + 1] == 'e' && buf[p + 2] == 'r' && buf[p + 3] == 'o') {
|
||||
p += 3;
|
||||
buf[p] = '0';
|
||||
}
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
/* TODO: this is slow */
|
||||
if (newstr != NULL) {
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define WSZ 64
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
int i, len = strlen(data);
|
||||
char w0[WSZ];
|
||||
char w1[WSZ];
|
||||
char w2[WSZ];
|
||||
char w3[WSZ];
|
||||
char w4[WSZ];
|
||||
char *buf, *ptr, *optr;
|
||||
|
||||
if (!strcmp(data, "jr ra")) {
|
||||
strcpy(str, "ret");
|
||||
return true;
|
||||
}
|
||||
|
||||
// malloc can be slow here :?
|
||||
if (!(buf = malloc(len + 1))) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf, data, len + 1);
|
||||
|
||||
rz_str_replace_char(buf, '(', ',');
|
||||
rz_str_replace_char(buf, ')', ' ');
|
||||
rz_str_trim(buf);
|
||||
|
||||
if (*buf) {
|
||||
w0[0] = '\0';
|
||||
w1[0] = '\0';
|
||||
w2[0] = '\0';
|
||||
w3[0] = '\0';
|
||||
w4[0] = '\0';
|
||||
ptr = strchr(buf, ' ');
|
||||
if (!ptr) {
|
||||
ptr = strchr(buf, '\t');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w0, buf, WSZ - 1);
|
||||
strncpy(w1, ptr, WSZ - 1);
|
||||
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w1, optr, WSZ - 1);
|
||||
strncpy(w2, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w2, optr, WSZ - 1);
|
||||
strncpy(w3, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
// bonus
|
||||
ptr = strchr(ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
;
|
||||
}
|
||||
strncpy(w3, optr, WSZ - 1);
|
||||
strncpy(w4, ptr, WSZ - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strncpy(w0, buf, WSZ - 1);
|
||||
}
|
||||
{
|
||||
const char *wa[] = { w0, w1, w2, w3, w4 };
|
||||
int nw = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (wa[i][0] != '\0') {
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str);
|
||||
{
|
||||
char *p = strdup(str);
|
||||
p = rz_str_replace(p, "+ -", "- ", 0);
|
||||
p = rz_str_replace(p, " + ]", " + 0]", 0);
|
||||
|
||||
p = rz_str_replace(p, "zero", "0", 1);
|
||||
if (!strncmp(p, "0 = ", 4)) {
|
||||
*p = 0; // nop
|
||||
}
|
||||
if (!strcmp(w1, w2)) {
|
||||
char a[32], b[32];
|
||||
#define REPLACE(x, y) \
|
||||
do { \
|
||||
int snprintf_len1_ = snprintf(a, 32, x, w1, w1); \
|
||||
int snprintf_len2_ = snprintf(b, 32, y, w1); \
|
||||
if (snprintf_len1_ < 32 && snprintf_len2_ < 32) { \
|
||||
p = rz_str_replace(p, a, b, 0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// TODO: optimize
|
||||
REPLACE("%s = %s +", "%s +=");
|
||||
REPLACE("%s = %s -", "%s -=");
|
||||
REPLACE("%s = %s &", "%s &=");
|
||||
REPLACE("%s = %s |", "%s |=");
|
||||
REPLACE("%s = %s ^", "%s ^=");
|
||||
REPLACE("%s = %s >>", "%s >>=");
|
||||
REPLACE("%s = %s <<", "%s <<=");
|
||||
}
|
||||
p = rz_str_replace(p, ":", "0000", 0);
|
||||
strcpy(str, p);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
return true;
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (insert_zero) {
|
||||
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&mips_config, assembly, sb);
|
||||
}
|
||||
|
||||
static bool subvar(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char *data, char *str, int len) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2015-2017 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -1615,7 +1616,7 @@ static int replace(int argc, const char *argv[], char *newstr) {
|
|||
}
|
||||
|
||||
#define WSZ 128
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
|
||||
int i, len = strlen(data);
|
||||
char w0[WSZ];
|
||||
char w1[WSZ];
|
||||
|
|
@ -1623,10 +1624,11 @@ static int parse(RzParse *p, const char *data, char *str) {
|
|||
char w3[WSZ];
|
||||
char w4[WSZ];
|
||||
char w5[WSZ];
|
||||
char str[1024] = { 0 };
|
||||
char *buf, *ptr, *optr;
|
||||
|
||||
if (!strcmp(data, "jr ra")) {
|
||||
strcpy(str, "return");
|
||||
rz_strbuf_set(sb, "return");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1748,6 +1750,7 @@ static int parse(RzParse *p, const char *data, char *str) {
|
|||
}
|
||||
}
|
||||
free(buf);
|
||||
rz_strbuf_set(sb, str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,8 +107,9 @@ static int replace(int argc, const char *argv[], char *newstr) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
|
||||
char w0[256], w1[256], w2[256], w3[256];
|
||||
char str[1024] = { 0 };
|
||||
int i, len = strlen(data), n;
|
||||
char *buf, *ptr, *optr, *num;
|
||||
|
||||
|
|
@ -214,6 +215,7 @@ static int parse(RzParse *p, const char *data, char *str) {
|
|||
free(s);
|
||||
}
|
||||
free(buf);
|
||||
rz_strbuf_set(sb, str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2017 deroad <wargio@libero.it>
|
||||
// SPDX-FileCopyrightText: 2017-2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -11,258 +11,165 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ "add", "B += A" },
|
||||
{ "addc", "B += A + t" },
|
||||
{ "addv", "B += A; t = int_overflow (B)" },
|
||||
{ "and", "B &= A" },
|
||||
{ "and.b", "B &= A" },
|
||||
{ "bf", "if (!t) goto A" },
|
||||
{ "bf.s", "if (!t) goto A" },
|
||||
{ "bra", "goto A" },
|
||||
{ "brk", "_break_exception ()" },
|
||||
{ "bsr", "A ()" },
|
||||
{ "bsrf", "A ()" },
|
||||
{ "bt", "if (t) goto A" },
|
||||
{ "bt.s", "if (t) goto A" },
|
||||
{ "clrmac", "_clrmac ()" },
|
||||
{ "clrs", "_clrs ()" },
|
||||
{ "clrt", "_clrt ()" },
|
||||
{ "cmp/eq", "t = B == A ? 1 : 0" },
|
||||
{ "cmp/ge", "t = B >= A ? 1 : 0" },
|
||||
{ "cmp/gt", "t = B > A ? 1 : 0" },
|
||||
{ "cmp/hi", "t = (unsigned) B > (unsigned) A ? 1 : 0" },
|
||||
{ "cmp/hs", "t = (unsigned) B >= (unsigned) A ? 1 : 0" },
|
||||
{ "cmp/pl", "t = A > 0 ? 1 : 0" },
|
||||
{ "cmp/pz", "t = A >= 0 ? 1 : 0" },
|
||||
{ "cmp/str", "t = A ^ B ? 1 : 0" },
|
||||
{ "div1", "B /= A" },
|
||||
{ "dmuls.l", "mac = B * A" },
|
||||
{ "dmulu.l", "mac = (unsigned) B * (unsigned) A" },
|
||||
{ "dt", "A--; t = !A ? 1 : 0" },
|
||||
{ "exts.b", "B = (int) A" },
|
||||
{ "extu.b", "B = (unsigned int) A" },
|
||||
{ "exts.w", "B = (int) A" },
|
||||
{ "extu.w", "B = (unsigned int) A" },
|
||||
{ "fabs", "A = abs (A)" },
|
||||
{ "fadd", "B += A" },
|
||||
{ "fcmp/eq", "t = B == A ? 1 : 0" },
|
||||
{ "fcmp/gt", "t = B > A ? 1 : 0" },
|
||||
{ "fcnvds", "B = A" },
|
||||
{ "fdiv", "B /= A" },
|
||||
{ "flds", "B = A" },
|
||||
{ "fldi0", "A = 0.0f" },
|
||||
{ "fldi1", "A = 1.0f" },
|
||||
{ "float", "B = A" },
|
||||
{ "fmac", "C += A * B" },
|
||||
{ "fmov", "B = A" },
|
||||
{ "fmov.s", "B = A" },
|
||||
{ "fmul", "B *= A" },
|
||||
{ "fneg", "A = -A" },
|
||||
{ "fsqrt", "A = sqrt (A)" },
|
||||
{ "fsts", "B = A" },
|
||||
{ "fsub", "B -= A" },
|
||||
{ "ftrc", "B = trunc (A)" },
|
||||
{ "ftrv", "B *= A" },
|
||||
{ "jmp", "goto A" },
|
||||
{ "jsr", "A ()" },
|
||||
{ "ldr", "B = A" },
|
||||
{ "ldr.l", "B = A" },
|
||||
{ "lds", "B = A" },
|
||||
{ "lds.l", "B = A" },
|
||||
{ "mov", "B = A" },
|
||||
{ "mov.b", "B = A" },
|
||||
{ "mov.l", "B = A" },
|
||||
{ "mov.w", "B = A" },
|
||||
{ "movca.l", "B = A" },
|
||||
{ "movt", "A = t" },
|
||||
{ "muls.w", "macl = A * B" },
|
||||
{ "mulu.w", "macl = (unsigned) A * (unsigned) B" },
|
||||
{ "neg", "A = -A" },
|
||||
{ "negc", "A = (-A) - t" },
|
||||
{ "nop", "" },
|
||||
{ "not", "A = !A" },
|
||||
{ "or", "B |= A" },
|
||||
{ "rotcl", "t = A & 0x80000000 ? 0 : 1; A = (A << 1) | t" },
|
||||
{ "rotl", "A = (A << 1) | (A >> 31)" },
|
||||
{ "rotr", "A = (A << 31) | (A >> 1)" },
|
||||
{ "rte", "_rte ()" },
|
||||
{ "rts", "return" },
|
||||
{ "sets", "s = 1" },
|
||||
{ "sett", "t = 1" },
|
||||
{ "shad", "B = A >= 0 ? B << A : B >> (31 - A)" },
|
||||
{ "shal", "A <<= 1" },
|
||||
{ "shar", "A >>= 1" },
|
||||
{ "shld", "B = A >= 0 ? B << A : B >> (31 - A)" },
|
||||
{ "shll", "A <<= 1" },
|
||||
{ "shll2", "A <<= 2" },
|
||||
{ "shll8", "A <<= 8" },
|
||||
{ "shll16", "A <<= 16" },
|
||||
{ "shlr", "A >>= 1" },
|
||||
{ "shlr2", "A >>= 2" },
|
||||
{ "shlr8", "A >>= 8" },
|
||||
{ "shlr16", "A >>= 16" },
|
||||
{ "sleep", "_halt ()" },
|
||||
{ "stc", "B = A" },
|
||||
{ "stc.l", "B = A" },
|
||||
{ "sts", "B = A" },
|
||||
{ "sts.l", "B = A" },
|
||||
{ "sub", "B -= A" },
|
||||
{ "subc", "B -= A - t" },
|
||||
{ "subv", "B -= A; t = int_underflow (B)" },
|
||||
{ "swap.b", "swap_byte (B, A)" },
|
||||
{ "swap.w", "swap_word (B, A)" },
|
||||
{ "tas.b", "test_and_set (A)" },
|
||||
{ "trapa", "trap (A)" },
|
||||
{ "tst", "t = B & A ? 0 : 1" },
|
||||
{ "xor", "B ^= A" },
|
||||
{ "xor.b", "B ^= A" },
|
||||
{ NULL }
|
||||
};
|
||||
#include "parse_common.c"
|
||||
|
||||
for (i = 0; ops[i].op != NULL; i++) {
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
if (newstr != NULL) {
|
||||
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
|
||||
if (ops[i].str[j] >= 'A' && ops[i].str[j] <= 'J') {
|
||||
const char *w = argv[ops[i].str[j] - '@'];
|
||||
if (w != NULL) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static RzList *sh_tokenize(const char *assembly, size_t length);
|
||||
|
||||
static const RzPseudoGrammar sh_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "2 += 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addc", "2 += 1 + t"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addv", "2 += 1; t = int_overflow (2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and", "2 &= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and.b", "2 &= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bf", "if (!t) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bf.s", "if (!t) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bra", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("brk", "_break_exception ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bsr", "1 ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bsrf", "1 ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bt", "if (t) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bt.s", "if (t) goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clrmac", "_clrmac ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clrs", "_clrs ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clrt", "_clrt ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/eq", "t = 2 == 1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/ge", "t = 2 >= 1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/gt", "t = 2 > 1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/hi", "t = (unsigned) 2 > (unsigned) 1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/hs", "t = (unsigned) 2 >= (unsigned) 1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/pl", "t = 1 > 0 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/pz", "t = 1 >= 0 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/str", "t = 1 ^ 2 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("div1", "2 /= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dmuls.l", "mac = 2 * 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dmulu.l", "mac = (unsigned) 2 * (unsigned) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dt", "1--; t = !1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("exts.b", "2 = (int) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("exts.w", "2 = (int) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("extu.b", "2 = (unsigned int) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("extu.w", "2 = (unsigned int) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fabs", "1 = abs (1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fadd", "2 += 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fcmp/eq", "t = 2 == 1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fcmp/gt", "t = 2 > 1 ? #1 : 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fcnvds", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fdiv", "2 /= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fldi0", "1 = 0.0f"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fldi1", "1 = #1.0f"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("flds", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("float", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fmac", "3 += 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fmov", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fmov.s", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fmul", "2 *= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fneg", "1 = -1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fsqrt", "1 = sqrt (1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fsts", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("fsub", "2 -= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ftrc", "2 = trunc (1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ftrv", "2 *= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jsr", "1 ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldr", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldr.l", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lds", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lds.l", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mov.b", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mov.l", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mov.w", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movca.l", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movt", "1 = t"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("muls.w", "macl = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mulu.w", "macl = (unsigned) 1 * (unsigned) 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = -1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("negc", "1 = (-1) - t"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("not", "1 = !1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or", "2 |= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rotcl", "t = 1 & 0x#80000000 ? 0 : #1; 1 = (1 << #1) | t"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rotl", "1 = (1 << #1) | (1 >> #31)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rotr", "1 = (1 << #31) | (1 >> #1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rte", "_rte ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rts", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sets", "s = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sett", "t = #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shad", "2 = 1 >= 0 ? 2 << 1 | 2 >> (#31 - 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shal", "1 <<= #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shar", "1 >>= #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shld", "2 = 1 >= 0 ? 2 << 1 | 2 >> (#31 - 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shll", "1 <<= #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shll#16", "1 <<= #16"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shll2", "1 <<= #2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shll8", "1 <<= #8"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shlr", "1 >>= #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shlr#16", "1 >>= #16"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shlr2", "1 >>= #2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shlr8", "1 >>= #8"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sleep", "_halt ()"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stc", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stc.l", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sts", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sts.l", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "2 -= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subc", "2 -= 1 - t"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subv", "2 -= 1; t = int_underflow (2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("swap.b", "swap_byte (2, 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("swap.w", "swap_word (2, 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tas.b", "test_and_set (1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("trapa", "trap (1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "t = 2 & 1 ? 0 : #1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "2 ^= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor.b", "2 ^= 1"),
|
||||
};
|
||||
|
||||
static const RzPseudoReplace sh_replace[] = {
|
||||
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig sh_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(sh_lexicon, sh_replace, 4, sh_tokenize);
|
||||
|
||||
RzList *sh_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
bool ignore_comma = false;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO: this is slow */
|
||||
if (newstr != NULL) {
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',' && !ignore_comma) {
|
||||
p++;
|
||||
} else if (buf[p] == '(') {
|
||||
ignore_comma = true;
|
||||
} else if (buf[p] == ')') {
|
||||
ignore_comma = false;
|
||||
}
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
return false;
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzListIter *it;
|
||||
rz_list_foreach (tokens, it, buf) {
|
||||
it->data = rz_str_replace(buf, ",", " + ", 1);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
#define WSZ 128
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
int i, len = strlen(data);
|
||||
char w0[WSZ];
|
||||
char w1[WSZ];
|
||||
char w2[WSZ];
|
||||
char w3[WSZ];
|
||||
char w4[WSZ];
|
||||
char *buf, *ptr, *optr, *par;
|
||||
|
||||
// malloc can be slow here :?
|
||||
if (!(buf = malloc(len + 1))) {
|
||||
return false;
|
||||
}
|
||||
memcpy(buf, data, len + 1);
|
||||
|
||||
rz_str_trim(buf);
|
||||
if (*buf) {
|
||||
w0[0] = '\0';
|
||||
w1[0] = '\0';
|
||||
w2[0] = '\0';
|
||||
w3[0] = '\0';
|
||||
w4[0] = '\0';
|
||||
ptr = strchr(buf, ' ');
|
||||
if (!ptr) {
|
||||
ptr = strchr(buf, '\t');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w0, buf, WSZ - 1);
|
||||
strncpy(w1, ptr, WSZ - 1);
|
||||
|
||||
optr = ptr;
|
||||
par = strchr(ptr, '(');
|
||||
if (par && strchr(ptr, ',') > par) {
|
||||
ptr = strchr(ptr, ')');
|
||||
if (ptr) {
|
||||
ptr = strchr(ptr, ',');
|
||||
}
|
||||
} else {
|
||||
ptr = strchr(ptr, ',');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w1, optr, WSZ - 1);
|
||||
strncpy(w2, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
par = strchr(ptr, '(');
|
||||
if (par && strchr(ptr, ',') > par) {
|
||||
ptr = strchr(ptr, ')');
|
||||
if (ptr) {
|
||||
ptr = strchr(ptr, ',');
|
||||
}
|
||||
} else {
|
||||
ptr = strchr(ptr, ',');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w2, optr, WSZ - 1);
|
||||
strncpy(w3, ptr, WSZ - 1);
|
||||
optr = ptr;
|
||||
// bonus
|
||||
par = strchr(ptr, '(');
|
||||
if (par && strchr(ptr, ',') > par) {
|
||||
ptr = strchr(ptr, ')');
|
||||
if (ptr) {
|
||||
ptr = strchr(ptr, ',');
|
||||
}
|
||||
} else {
|
||||
ptr = strchr(ptr, ',');
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr == ' '; ptr++) {
|
||||
//nothing to see here
|
||||
}
|
||||
strncpy(w3, optr, WSZ - 1);
|
||||
strncpy(w4, ptr, WSZ - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strncpy(w0, buf, WSZ - 1);
|
||||
}
|
||||
{
|
||||
const char *wa[] = { w0, w1, w2, w3, w4 };
|
||||
int nw = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (wa[i][0] != '\0') {
|
||||
nw++;
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str);
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return true;
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&sh_config, assembly, sb);
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_sh_pseudo = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2020 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_lib.h>
|
||||
|
|
@ -7,172 +7,114 @@
|
|||
#include <rz_parse.h>
|
||||
|
||||
// https://www.ti.com/lit/ug/spru732j/spru732j.pdf
|
||||
#include "parse_common.c"
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
int narg;
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ 3, "add", "3 = 1 + 2" }, // add b12, b1, b9 -> b9 = b12 + b1
|
||||
{ 3, "addu", "3 = 1 + 2" },
|
||||
{ 3, "addw", "3 = 1 + 2" },
|
||||
{ 3, "addaw", "3 = 1 + 2" },
|
||||
{ 3, "addab", "3 = 1 + 2" },
|
||||
{ 3, "addah", "3 = 1 + 2" },
|
||||
{ 2, "addk", "2 += 1" }, // addk 123, b0 -> b0 += 123
|
||||
{ 3, "sadd", "3 = 1 + 2" }, // sadd b12, b1, b9 -> b9 = b12 + b1
|
||||
{ 3, "sadd2", "3 = 1 + 2" }, // sadd2 b12, b1, b9 -> b9 = b12 + b1
|
||||
{ 3, "sub", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
|
||||
{ 3, "subu", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
|
||||
{ 3, "sub2", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
|
||||
{ 3, "subab", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
|
||||
{ 3, "ssub", "3 = 1 - 2" }, // ssub b12, b1, b9 -> b9 = b12 - b1
|
||||
{ 2, "mv", "2 = 1" },
|
||||
{ 2, "mvk", "2 = 1" }, // mvk 1, a0 -> a0 = 1
|
||||
{ 2, "mvklh", "2 = (half) 1" }, // mvk 1, a0 -> a0 = 1
|
||||
{ 3, "band", "3 = 1 & 2" }, //
|
||||
{ 1, "zero", "1 = zero" },
|
||||
{ 3, "andn", "4 = 1 ~ 2" }, //
|
||||
{ 3, "cmpgtu", "3 = 1 cmpgtu 2" }, //
|
||||
{ 3, "cmpeq", "3 = 1 == 2" }, //
|
||||
{ 3, "cmpge", "3 = 1 >= 2" }, //
|
||||
{ 3, "cmplt", "3 = 1 <= 2" }, //
|
||||
{ 3, "smpylh", "3 = 1 * 2" }, //
|
||||
{ 3, "smpy", "3 = 1 * 2" }, //
|
||||
{ 3, "smpyh", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyu4", "3 = 1 * 2" }, //
|
||||
{ 3, "avg2", "3 = 1 avg 2" }, //
|
||||
{ 3, "pack2", "3 = 1 pack 2" }, //
|
||||
{ 3, "smpy", "3 = 1 * 2" }, //
|
||||
{ 3, "max2", "3 = max(1, 2)" }, //
|
||||
{ 3, "mpy", "3 = 1 * 2" }, //
|
||||
{ 3, "mpy2", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyu", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyh", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhl", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhl", "3 = 1 * 2" }, //
|
||||
{ 3, "mpylh", "3 = 1 * 2" }, //
|
||||
{ 3, "mpysu", "3 = 1 * 2" }, //
|
||||
{ 3, "smpyhl", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhlu", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhslu", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyluhs", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhi", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhu", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhus", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhsu", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhul", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhuls", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyhir", "3 = 1 * 2" }, //
|
||||
{ 3, "mpyli", "3 = 1 * 2" }, //
|
||||
{ 3, "mpylir", "3 = 1 * 2" }, //
|
||||
{ 4, "ext", "4 = 2 ext 1 .. 3" }, //
|
||||
{ 4, "extu", "4 = 2 ext 1 .. 3" }, //
|
||||
{ 0, "reti", "ret" }, // reti -> ret
|
||||
{ 2, "lddw", "2 = (word)1" }, // lddw
|
||||
{ 2, "ldhu", "2 = (half)1" }, // ldhu
|
||||
{ 2, "ldb", "2 = (byte)1" }, // ldb
|
||||
{ 2, "ldbu", "2 = (byte)1" }, // ldbu
|
||||
{ 2, "ldndw", "2 = 1" }, // ldbu
|
||||
{ 2, "ldnw", "2 = 1" }, // ldbu
|
||||
{ 2, "ldw", "2 = (word)1" }, // ldw
|
||||
{ 2, "ldh", "2 = (half)1" }, // ldw
|
||||
{ 2, "stb", "2 = (byte)1" }, // stb
|
||||
{ 2, "stw", "2 = (word)1" }, // stw
|
||||
{ 2, "sth", "2 = (half)1" }, // stw
|
||||
{ 2, "stnw", "2 = (word)1" }, // stw
|
||||
{ 2, "stdw", "2 = (half)1" }, // stw
|
||||
{ 2, "stndw", "2 = (half)1" }, // stw
|
||||
{ 3, "or", "3 = 2 | 1" },
|
||||
{ 3, "shl", "3 = (2 & Oxffffff) << 1" },
|
||||
{ 3, "shr", "3 = (2 & Oxffffff) << 1" },
|
||||
{ 3, "shlmb", "3 = << 1" },
|
||||
{ 4, "set", "4 = 2 .bitset 1 .. 2" }, // set a29,0x1a, 1, a19
|
||||
{ 4, "clr", "4 = 2 .bitclear 1 .. 2" }, // clr a29,0x1a, 1, a19
|
||||
{ 0, "invalid", "" },
|
||||
{ 0, "nop", "" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
if (!newstr) {
|
||||
return false;
|
||||
static RzList *tms320_tokenize(const char *assembly, size_t length);
|
||||
|
||||
static const RzPseudoGrammar tms320_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addab", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addah", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addaw", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addk", "2 += 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addu", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addw", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("andn", "3 = 1 ~ 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("avg2", "3 = 1 avg 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("b", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("band", "3 = 1 & 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clr", "4 = 2 .bitclear 1 .. 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpeq", "3 = 1 == 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpge", "3 = 1 >= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmpgtu", "3 = 1 > 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmplt", "3 = 1 < 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ext", "4 = 2 ext 1 .. 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("extu", "4 = 2 ext 1 .. 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldb", "2 = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldbu", "2 = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("lddw", "2 = (word) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldh", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldhu", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldndw", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldnw", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldw", "2 = (word) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("max2", "3 = max(1, 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpy", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpy2", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyh", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhi", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhir", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhl", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhl", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhlu", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhslu", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhsu", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhu", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhul", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhuls", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhus", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpylh", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyli", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpylir", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyluhs", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpysu", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyu", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mpyu4", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mv", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mvk", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mvklh", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or", "3 = 2 | 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("pack2", "3 = 1 pack 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("reti", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sadd", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sadd2", "3 = 1 + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("set", "4 = 2 .bitset 1 .. 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shl", "3 = (2 & #0xffffff) << 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shlmb", "3 = << 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shr", "3 = (2 & #0xffffff) << 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("smpy", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("smpy", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("smpyh", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("smpyhl", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("smpylh", "3 = 1 * 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ssub", "3 = 1 - 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stb", "2 = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stdw", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sth", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stndw", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stnw", "2 = (word) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stw", "2 = (word) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "3 = 1 - 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub2", "3 = 1 - 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subab", "3 = 1 - 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("subu", "3 = 1 - 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("zero", "1 = 0"),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig tms320_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(tms320_lexicon, 5, tms320_tokenize);
|
||||
|
||||
RzList *tms320_tokenize(const char *assembly, size_t length) {
|
||||
char *buf = NULL, *sp = NULL;
|
||||
RzList *tokens = NULL;
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; ops[i].op; i++) {
|
||||
if (ops[i].narg) {
|
||||
if (argc - 1 != ops[i].narg) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
for (j = k = 0; ops[i].str[j]; j++, k++) {
|
||||
if (IS_DIGIT(ops[i].str[j])) {
|
||||
int index = ops[i].str[j] - '0';
|
||||
if (index >= 0 && index < argc) {
|
||||
const char *w = argv[index];
|
||||
if (!RZ_STR_ISEMPTY(w)) {
|
||||
rz_str_cpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
if (argc == 4 && argv[2][0] == '[') {
|
||||
strcat(newstr + k, "+");
|
||||
strcat(newstr + k + 3, argv[2]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
sp = strchr(buf, ' ');
|
||||
if (sp) {
|
||||
*sp = ',';
|
||||
}
|
||||
|
||||
/* TODO: this is slow */
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ",");
|
||||
}
|
||||
return false;
|
||||
tokens = rz_str_split_duplist(buf, ",", true);
|
||||
free(buf);
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
if (!strncmp(data, "|| ", 3)) {
|
||||
data += 3;
|
||||
}
|
||||
if (RZ_STR_ISEMPTY(data)) {
|
||||
*str = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *buf = strdup(data);
|
||||
|
||||
RzListIter *iter;
|
||||
char *sp = strchr(buf, ' ');
|
||||
size_t nw = 1;
|
||||
const char *wa[5] = { 0 };
|
||||
wa[0] = buf;
|
||||
RzList *list = NULL;
|
||||
if (sp) {
|
||||
*sp++ = 0;
|
||||
list = rz_str_split_list(sp, ",", 0);
|
||||
char *w;
|
||||
rz_list_foreach (list, iter, w) {
|
||||
wa[nw] = w;
|
||||
nw++;
|
||||
if (nw == 5) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str);
|
||||
|
||||
free(buf);
|
||||
rz_list_free(list);
|
||||
|
||||
return true;
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&tms320_config, assembly, sb);
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_tms320_pseudo = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2020 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_lib.h>
|
||||
|
|
@ -8,194 +8,132 @@
|
|||
|
||||
// https://www.renesas.com/us/en/doc/products/mpumcu/doc/v850/r01us0037ej0100_v850e2.pdf
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
int narg;
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ 0, "ei", "enable-interrupts" },
|
||||
{ 0, "di", "disable-interrupts" },
|
||||
{ 0, "reti", "ret" },
|
||||
{ 2, "ld.hu", "2 = 1" },
|
||||
{ 1, "zxb", "1 = O" },
|
||||
{ 1, "zxh", "1 = O" },
|
||||
{ 1, "zxw", "1 = O" },
|
||||
{ 2, "set1", "2 |= (I << 2)" },
|
||||
{ 2, "clr1", "2 &= ~(I << 2)" },
|
||||
{ 2, "sld.w", "2 = (word) 1" },
|
||||
{ 2, "sld.h", "2 = (half) 1" },
|
||||
{ 2, "sld.b", "2 = (byte) 1" },
|
||||
{ 2, "ld.bu", "2 = 1" },
|
||||
{ 2, "ld.w", "2 = (word) 1" },
|
||||
{ 2, "ld.h", "2 = (half) 1" },
|
||||
{ 2, "ld.b", "2 = (byte) 1" },
|
||||
{ 2, "st.h", "2 = (half) 1" },
|
||||
{ 2, "st.w", "2 = (word) 1" },
|
||||
{ 2, "st.b", "2 = (byte) 1" },
|
||||
{ 2, "sst.w", "2 = (word) 1" },
|
||||
{ 2, "sst.h", "2 = (half) 1" },
|
||||
{ 2, "sst.b", "2 = (byte) 1" },
|
||||
{ 2, "stsr", "2 = 1" },
|
||||
{ 2, "ldsr", "2 = 1" },
|
||||
{ 2, "and", "3 = 2 & 1" },
|
||||
{ 3, "andi", "3 = 2 & 1" },
|
||||
{ 2, "add", "2 += 1" },
|
||||
{ 3, "addi", "3 = 2 + 1" },
|
||||
{ 2, "sub", "2 -= 1" },
|
||||
{ 2, "divh", "2 /= 1" },
|
||||
{ 3, "divh", "3 = 2 / 1" },
|
||||
{ 2, "mulh", "2 *= 1" },
|
||||
{ 3, "mul", "3 = 2 * 1" },
|
||||
{ 3, "mulf.s", "3 = 2 * 1" },
|
||||
{ 2, "shl", "2 <<= 1" },
|
||||
{ 2, "shr", "2 >>= 1" },
|
||||
{ 2, "xor", "2 ^= 1" },
|
||||
{ 3, "xori", "3 = 1 ^ 2" },
|
||||
{ 2, "tst", "2 == 1" },
|
||||
{ 2, "tst1", "2 == 1" },
|
||||
{ 1, "jr", "jmp 1" },
|
||||
{ 2, "cmp", "2 == 1" },
|
||||
{ 4, "cmov", "4 == 1 ? 2 : 3" },
|
||||
{ 2, "mov", "2 = 1" },
|
||||
{ 3, "movhi", "3 = (1 << XX) + 2" },
|
||||
{ 3, "movea", "3 = 1 & 2" },
|
||||
{ 3, "ori", "3 = 1 | 2" },
|
||||
{ 2, "jarl", "call 1 # 2" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
if (!newstr) {
|
||||
return false;
|
||||
#include "parse_common.c"
|
||||
|
||||
static RzList *v850_tokenize(const char *assembly, size_t length);
|
||||
|
||||
static const RzPseudoGrammar v850_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "2 += 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("addi", "3 = 2 + 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and", "3 = 2 & 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "3 = 2 & 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("clr1", "2 &= ~(#1 << 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmov", "4 == 1 ? 2 : 3"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "2 == 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("di", "disable-interrupts"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("divh", "2 /= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("divh", "3 = 2 / 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ei", "enable-interrupts"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jarl", "call 1 # 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jr", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ld.b", "3 = (byte) *(2 + 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ld.bu", "3 = (unsigned byte) *(2 + 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ld.h", "3 = (Zhalf) *(2 + 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ld.hu", "3 = (unsigned half) *(2 + 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ld.w", "3 = (word) *(2 + 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldsr", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movea", "3 = 1 & 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("movhi", "3 = (1 << XX) + 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "3 = 2 * 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mulf.s", "3 = 2 * 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("mulh", "2 *= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("not", "2 = ~1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or", "3 = 2 | 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "3 = 2 | 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("reti", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("set1", "2 |= (#1 << 2)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shl", "2 <<= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("shr", "2 >>= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sld.b", "2 = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sld.h", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sld.w", "2 = (word) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sst.b", "2 = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sst.h", "2 = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sst.w", "2 = (word) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("st.b", "*(3 + 2) = (byte) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("st.h", "*(3 + 2) = (half) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("st.w", "*(3 + 2) = (word) 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("stsr", "2 = 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "2 -= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "2 == 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("tst1", "2 == 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "2 ^= 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xori", "3 = 1 ^ 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("zxb", "1 = 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("zxh", "1 = 0"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("zxw", "1 = 0"),
|
||||
};
|
||||
|
||||
static const RzPseudoReplace v850_replace[] = {
|
||||
RZ_PSEUDO_DEFINE_REPLACE(" + 0)", ")", 0),
|
||||
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
|
||||
RZ_PSEUDO_DEFINE_REPLACE(",", "", 1),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig v850_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(v850_lexicon, v850_replace, 4, v850_tokenize);
|
||||
|
||||
static const char *v850_short_op[] = {
|
||||
"and",
|
||||
"or",
|
||||
};
|
||||
|
||||
RzList *v850_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
bool insert_zero = false;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; ops[i].op; i++) {
|
||||
if (ops[i].narg) {
|
||||
if (argc - 1 != ops[i].narg) {
|
||||
continue;
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
p++;
|
||||
} else if (buf[p] == '[') {
|
||||
buf[p] = ' ';
|
||||
if (!IS_HEXCHAR(buf[p - 1])) {
|
||||
p++;
|
||||
insert_zero = true;
|
||||
}
|
||||
} else if (buf[p] == ']') {
|
||||
buf[p] = ' ';
|
||||
if (buf[p + 1] == ',') {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
for (j = k = 0; ops[i].str[j]; j++, k++) {
|
||||
if (IS_DIGIT(ops[i].str[j])) {
|
||||
int index = ops[i].str[j] - '0';
|
||||
if (index >= 0 && index < argc) {
|
||||
const char *w = argv[index];
|
||||
if (!RZ_STR_ISEMPTY(w)) {
|
||||
rz_str_cpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
}
|
||||
} else if (ops[i].str[j] == 'X') {
|
||||
newstr[k] = '1';
|
||||
k++;
|
||||
j++;
|
||||
newstr[k] = '6';
|
||||
} else if (ops[i].str[j] == 'I') {
|
||||
newstr[k] = '1';
|
||||
} else if (ops[i].str[j] == 'O') {
|
||||
newstr[k] = '0';
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
if (argc == 4 && argv[2][0] == '[') {
|
||||
strcat(newstr + k, "+");
|
||||
strcat(newstr + k + 3, argv[2]);
|
||||
}
|
||||
return true;
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
/* TODO: this is slow */
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ",");
|
||||
}
|
||||
rz_str_replace_in(newstr, strlen(newstr), "+= -", "-= ", true);
|
||||
rz_str_replace_in(newstr, strlen(newstr), " + -", " - ", true);
|
||||
// strcpy (newstr, a);
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *reorder(char *buf) {
|
||||
char *arr = strstr(buf, "-0x");
|
||||
if (!arr) {
|
||||
arr = strstr(buf, "0x");
|
||||
}
|
||||
if (!arr) {
|
||||
return buf;
|
||||
}
|
||||
char *par = strchr(arr + 2, '[');
|
||||
if (par) {
|
||||
char arg[32], reg[32];
|
||||
char *end = strchr(par + 1, ']');
|
||||
if (end) {
|
||||
rz_str_ncpy(reg, par + 1, end - par);
|
||||
rz_str_ncpy(arg, arr, par - arr + 1);
|
||||
sprintf(buf, "%s[%s]", reg, arg);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void guard_braces(char *buf) {
|
||||
bool braces = false;
|
||||
char *p = buf;
|
||||
for (; *p; p++) {
|
||||
switch (*p) {
|
||||
case '{':
|
||||
braces = true;
|
||||
break;
|
||||
case '}':
|
||||
braces = false;
|
||||
break;
|
||||
case ',':
|
||||
if (braces) {
|
||||
*p = ' ';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
if (!strncmp(data, "|| ", 3)) {
|
||||
data += 3;
|
||||
}
|
||||
if (RZ_STR_ISEMPTY(data)) {
|
||||
*str = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *buf = strdup(data);
|
||||
guard_braces(buf);
|
||||
RzListIter *iter;
|
||||
char *sp = strchr(buf, ' ');
|
||||
size_t nw = 1;
|
||||
const char *wa[5] = { 0 };
|
||||
wa[0] = buf;
|
||||
RzList *list = NULL;
|
||||
if (sp) {
|
||||
*sp++ = 0;
|
||||
list = rz_str_split_list(sp, ",", 0);
|
||||
char *w;
|
||||
rz_list_foreach (list, iter, w) {
|
||||
wa[nw] = reorder(w);
|
||||
nw++;
|
||||
if (nw == 5) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
replace(nw, wa, str);
|
||||
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
rz_list_free(list);
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
buf = rz_list_first(tokens);
|
||||
for (i = 0; i < RZ_ARRAY_SIZE(v850_short_op); ++i) {
|
||||
if (!strcmp(buf, v850_short_op[i])) {
|
||||
rz_list_insert(tokens, 1, strdup("0"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (insert_zero) {
|
||||
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&v850_config, assembly, sb);
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_v850_pseudo = {
|
||||
|
|
|
|||
|
|
@ -166,8 +166,9 @@ static int replace(int argc, char *argv[], char *newstr) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
|
||||
char w0[256], w1[256], w2[256], w3[256];
|
||||
char str[1024] = { 0 };
|
||||
int i;
|
||||
size_t len = strlen(data);
|
||||
int sz = 32;
|
||||
|
|
@ -285,6 +286,7 @@ static int parse(RzParse *p, const char *data, char *str) {
|
|||
replace(nw, wa, str);
|
||||
}
|
||||
free(buf);
|
||||
rz_strbuf_set(sb, str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2015 julien (jvoisin) voisin <julien.voisin@dustri.org>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -11,68 +11,145 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_parse.h>
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i, j, k;
|
||||
struct {
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ "adc", "1 = 1 + 2" },
|
||||
{ "add", "1 = 1 + 2" },
|
||||
{ "and", "1 = 1 & 2" },
|
||||
{ "cpl", "1 = ~1" },
|
||||
{ "ex", "swap(1, 2)" },
|
||||
{ "in", "1 = [2]" },
|
||||
{ "jp", "goto [1]" },
|
||||
{ "jp", "goto 1" },
|
||||
{ "jr", "goto +1" },
|
||||
{ "ld", "1 = 2" },
|
||||
{ "ldd", "1 = 2--" },
|
||||
{ "neg", "1 = -1" },
|
||||
{ "nop", "" },
|
||||
{ "or", "1 = 1 | 2" },
|
||||
{ "pop", "pop 1" },
|
||||
{ "push", "push 1" },
|
||||
{ "rr", "1 = 1 << 2" },
|
||||
{ "sbc", "1 = 1 - 2" },
|
||||
{ "sla", "1 = 1 << 2" },
|
||||
{ "sra", "1 = 1 >> 2" },
|
||||
{ "srl", "1 = 1 >> 2" },
|
||||
{ "sub", "1 = 1 - 2" },
|
||||
{ "xor", "1 = 1 ^ 2" },
|
||||
{ NULL }
|
||||
};
|
||||
#include "parse_common.c"
|
||||
|
||||
for (i = 0; ops[i].op != NULL; i++) {
|
||||
if (!strcmp(ops[i].op, argv[0])) {
|
||||
if (newstr != NULL) {
|
||||
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
|
||||
if (ops[i].str[j] >= '1' && ops[i].str[j] <= '9') {
|
||||
const char *w = argv[ops[i].str[j] - '0'];
|
||||
if (w != NULL) {
|
||||
strcpy(newstr + k, w);
|
||||
k += strlen(w) - 1;
|
||||
}
|
||||
} else {
|
||||
newstr[k] = ops[i].str[j];
|
||||
}
|
||||
}
|
||||
newstr[k] = '\0';
|
||||
static RzList *z80_tokenize(const char *assembly, size_t length);
|
||||
|
||||
// https://wikiti.brandonw.net/index.php?title=Z80_Instruction_Set
|
||||
static const RzPseudoGrammar z80_lexicon[] = {
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "1 += 2 + cf"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 += 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 &= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("bit", "tmp = 2 & (#1 << 1)"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("call", "call 1"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("ccf", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("cp", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("cpd", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("cpdr", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("cpi", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("cpir", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("cpl", "1 = ~1"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("daa", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("dec", "1--"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("di", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("djnz", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("ei", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ex", "swap(1, 2)"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("exx", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("halt", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("im", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("in", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("in", "1 = [2]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "1++"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("ind", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("indr", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("ini", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("inir", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jp", "goto 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jp", "goto [1]"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("jr", "goto +1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ld", "1 = 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ldd", "1 = 2--"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("lddr", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("ldi", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("ldir", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("mulub", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("muluw", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = -1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("or", "1 |= 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("otdr", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("otir", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("out", "1 = 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("outd", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("outi", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("pop", "pop 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("push", "push 1"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("res", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("ret", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("reti", "return"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("retn", "return"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rl", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rla", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rlc", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rlca", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rld", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rr", "1 <<= 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rra", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rrc", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rrca", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("rrd", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("rst", "call 1"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "1 -= 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("scf", "1 = 1 ? 2"),
|
||||
// RZ_PSEUDO_DEFINE_GRAMMAR("set", "1 = 1 ? 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sla", "1 <<= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sra", "1 >>= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("srl", "1 >>= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 -= 2"),
|
||||
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "1 ^= 2"),
|
||||
};
|
||||
|
||||
static const RzPseudoConfig z80_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(z80_lexicon, 3, z80_tokenize);
|
||||
|
||||
RzList *z80_tokenize(const char *assembly, size_t length) {
|
||||
size_t i, p;
|
||||
char *buf = NULL;
|
||||
const char *comma_replace = NULL;
|
||||
bool keep = false;
|
||||
RzList *tokens = NULL;
|
||||
|
||||
buf = rz_str_ndup(assembly, length);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0, p = 0; p < length; ++i, ++p) {
|
||||
if (buf[p] == ',') {
|
||||
if (!keep) {
|
||||
p++;
|
||||
} else if (buf[p + 1] == ' ') {
|
||||
buf[i] = buf[p];
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
} else if (buf[p] == '(') {
|
||||
keep = true;
|
||||
comma_replace = ", ";
|
||||
} else if (buf[p] == ')') {
|
||||
keep = false;
|
||||
}
|
||||
if (p > i) {
|
||||
buf[i] = buf[p];
|
||||
}
|
||||
}
|
||||
buf[i] = 0;
|
||||
|
||||
tokens = rz_str_split_duplist(buf, " ", true);
|
||||
free(buf);
|
||||
if (!tokens) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!strcmp((char *)rz_list_first(tokens), "call") && rz_list_length(tokens) == 3) {
|
||||
void *arg1 = rz_list_get_n(tokens, 1);
|
||||
void *arg2 = rz_list_get_n(tokens, 2);
|
||||
rz_list_set_n(tokens, 1, arg2);
|
||||
rz_list_set_n(tokens, 2, arg1);
|
||||
}
|
||||
|
||||
if (comma_replace) {
|
||||
RzListIter *it;
|
||||
rz_list_foreach (tokens, it, buf) {
|
||||
it->data = rz_str_replace(buf, ",", comma_replace, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: this is slow */
|
||||
if (newstr != NULL) {
|
||||
newstr[0] = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
strcat(newstr, argv[i]);
|
||||
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
return false;
|
||||
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
|
||||
return rz_pseudo_convert(&z80_config, assembly, sb);
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_z80_pseudo = {
|
||||
|
|
@ -80,7 +157,7 @@ RzParsePlugin rz_parse_plugin_z80_pseudo = {
|
|||
.desc = "z80 pseudo syntax",
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.replace = replace,
|
||||
.parse = parse,
|
||||
};
|
||||
|
||||
#ifndef RZ_PLUGIN_INCORE
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ RZ_API bool rz_parse_use(RzParse *p, const char *name) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
p->cur = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -98,13 +99,29 @@ RZ_API bool rz_parse_assemble(RzParse *p, char *data, char *str) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// data is input disasm, str is output pseudo
|
||||
// TODO: refactooring, this should return char * instead
|
||||
RZ_API bool rz_parse_parse(RzParse *p, const char *data, char *str) {
|
||||
rz_return_val_if_fail(p && data && str, false);
|
||||
return (p && data && *data && p->cur && p->cur->parse)
|
||||
? p->cur->parse(p, data, str)
|
||||
: false;
|
||||
/**
|
||||
* \brief Converts the assembly line into pseudocode
|
||||
*
|
||||
* Converts the assembly line into pseudocode
|
||||
* */
|
||||
RZ_API char *rz_parse_pseudocode(RzParse *p, const char *assembly) {
|
||||
rz_return_val_if_fail(p, NULL);
|
||||
if (RZ_STR_ISEMPTY(assembly)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzStrBuf *sb = rz_strbuf_new("");
|
||||
if (!sb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rz_strbuf_reserve(sb, 128);
|
||||
if (!p->cur || !p->cur->parse || !p->cur->parse(p, assembly, sb)) {
|
||||
rz_strbuf_free(sb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rz_strbuf_drain(sb);
|
||||
}
|
||||
|
||||
RZ_API char *rz_parse_immtrim(char *opstr) {
|
||||
|
|
|
|||
|
|
@ -939,7 +939,7 @@ address: 0x568
|
|||
opcode: push {r3, lr}
|
||||
esilcost: 16
|
||||
disasm: push {r3, lr}
|
||||
pseudo: push (r3, lr)
|
||||
pseudo: push (r3, lr)
|
||||
mnemonic: push
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ address: 0x100007f10
|
|||
opcode: irg x8, sp, x8
|
||||
esilcost: 0
|
||||
disasm: irg x8, sp, x8
|
||||
pseudo: irg x8,sp,x8
|
||||
pseudo: asm("irg x8, sp, x8")
|
||||
mnemonic: irg
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
|
|
@ -110,7 +110,7 @@ address: 0x100007f14
|
|||
opcode: addg x9, x8, 0x20, 0x0
|
||||
esilcost: 0
|
||||
disasm: addg x9, x8, 0x20, 0x0
|
||||
pseudo: addg x9,x8,0x20, 0x0
|
||||
pseudo: asm("addg x9, x8, 0x20, 0x0")
|
||||
mnemonic: addg
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
|
|
@ -141,7 +141,7 @@ address: 0x0
|
|||
opcode: addg x12, x8, 0x0, 0x2
|
||||
esilcost: 0
|
||||
disasm: addg x12, x8, 0x0, 0x2
|
||||
pseudo: addg x12,x8,0x0, 0x2
|
||||
pseudo: asm("addg x12, x8, 0x0, 0x2")
|
||||
mnemonic: addg
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
|
|
@ -158,7 +158,7 @@ address: 0x4
|
|||
opcode: addg x9, x8, 0x20, 0x0
|
||||
esilcost: 0
|
||||
disasm: addg x9, x8, 0x20, 0x0
|
||||
pseudo: addg x9,x8,0x20, 0x0
|
||||
pseudo: asm("addg x9, x8, 0x20, 0x0")
|
||||
mnemonic: addg
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
|
|
@ -175,7 +175,7 @@ address: 0x8
|
|||
opcode: irg x8, sp, x8
|
||||
esilcost: 0
|
||||
disasm: irg x8, sp, x8
|
||||
pseudo: irg x8,sp,x8
|
||||
pseudo: asm("irg x8, sp, x8")
|
||||
mnemonic: irg
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
|
|
|
|||
|
|
@ -25,3 +25,20 @@ EXPECT=<<EOF
|
|||
entry0 0x26e [CALL] invoke-direct {v0}, LHello.<init>()V ; 0x0
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=Dalvik HelloWorld func xref
|
||||
FILE=bins/dex/HelloWorld.dex
|
||||
CMDS=<<EOF
|
||||
aa
|
||||
e asm.pseudo=true
|
||||
pif @ sym.LHello.method._init___V
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
call Object.<init>V (v1)
|
||||
v0 = (wide) 0x1
|
||||
v1[(I)] = v0
|
||||
v0 = (wide) 0x2
|
||||
v0 = (I) LHello.localVar2
|
||||
return
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -5,3 +5,80 @@ EXPECT=<<EOF
|
|||
0x000009f2
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=M68k pseudo
|
||||
FILE=bins/smd/LiquidSpaceDodgerV3.bin
|
||||
CMDS=<<EOF
|
||||
e asm.pseudo=true
|
||||
af
|
||||
pif
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
d0 = 0xa10001
|
||||
d0 &= 0xf
|
||||
if (==) goto 0x216
|
||||
0xa14000 = 0x53454741
|
||||
sr = 0x2700
|
||||
0xa11100 = 0x100
|
||||
0xa11200 = 0x100
|
||||
a7 = sym.SSP
|
||||
call 0x9f2
|
||||
call 0xa72
|
||||
call 0x9ca
|
||||
call 0xa86
|
||||
a5 = 0x2338
|
||||
d4 = 0xbff
|
||||
(a3) = 0x40000000
|
||||
call 0x9ea
|
||||
a5 = 0x1db6
|
||||
(a3) = 0xc0000000
|
||||
d4 = 0x2f
|
||||
call 0x9ea
|
||||
call 0xae0
|
||||
a5 = 0x3b38
|
||||
(a3) = 0x5c000000
|
||||
d4 = 0x11ff
|
||||
call 0x9ea
|
||||
a5 = 0x5f38
|
||||
d4 = section.header
|
||||
(a3) = 0x58000000
|
||||
call 0x9ea
|
||||
a5 = 0x6138
|
||||
d4 = 0x24d0
|
||||
(a3) = 0x40000001
|
||||
call 0x9ea
|
||||
a5 = 0xaad8
|
||||
d4 = 0x7ff
|
||||
(a3) = 0x40000003
|
||||
call 0xa9a
|
||||
a5 = 0x2276
|
||||
d4 = 0
|
||||
(a3) = 0x60000002
|
||||
call 0x9a2
|
||||
0xff0022 = 0x1
|
||||
call 0x1c94
|
||||
0xff000e = 0x110
|
||||
0xff002e = 0xee
|
||||
0xff001e = 0x5
|
||||
0xff0030 = 0xff
|
||||
0xff0022 = 0x1
|
||||
0xff0020 = 0x1
|
||||
call 0xa2e
|
||||
sr = 0x2300
|
||||
0xff0014 = 0x0
|
||||
call 0x490
|
||||
call 0x3d0
|
||||
call 0xdd6
|
||||
call 0x36c
|
||||
call 0x4d4
|
||||
call 0x6d0
|
||||
call 0x1b8c
|
||||
0xff000a = 0xff
|
||||
0x1 += 0xff0014
|
||||
call 0x472
|
||||
0xff000a == 0
|
||||
if (!=) goto 0x33e
|
||||
goto 0x312
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ pd 1
|
|||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x80100000 0000beaf sw fp, (sp)
|
||||
0x80100000 0000beaf [sp + 0] = fp
|
||||
0x80100000 0000beaf word [sp] = fp
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,31 @@ nop
|
|||
EOF
|
||||
RUN
|
||||
|
||||
NAME=SuperH pseudo
|
||||
FILE=bins/sh/loop.elf
|
||||
CMDS=<<EOF
|
||||
s sym._called_in_loop
|
||||
e asm.pseudo=true
|
||||
af
|
||||
pif
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
@-r15 = r14
|
||||
r14 = r15
|
||||
r1 = @(0x14 + pc)
|
||||
r1 = @r1
|
||||
r2 = r1
|
||||
r2 += 0x01
|
||||
r1 = @(0xc + pc)
|
||||
@r1 = r2
|
||||
|
||||
r15 = r14
|
||||
r14 = @r15+
|
||||
return
|
||||
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=SuperH af
|
||||
FILE=--
|
||||
CMDS=<<EOF
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ EXPECT=<<EOF
|
|||
{
|
||||
"opcode": "la %r4, 8(%r15)",
|
||||
"disasm": "la %r4, 8(%r15)",
|
||||
"pseudo": "la %r4,8(%r15) ",
|
||||
"description": "Load Address",
|
||||
"mnemonic": "la",
|
||||
"mask": "ffffffff",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ EXPECT=<<EOF
|
|||
{
|
||||
"opcode": "b 0x20de8",
|
||||
"disasm": "b 0x20de8",
|
||||
"pseudo": "b 0x20de8 ",
|
||||
"pseudo": "goto 0x20de8",
|
||||
"mnemonic": "b",
|
||||
"mask": "ff000000",
|
||||
"jump": 134632,
|
||||
|
|
@ -54,150 +54,150 @@ EOF
|
|||
EXPECT=<<EOF
|
||||
a17 = (half) 0x13cf
|
||||
a28 = 0 ext a0 .. 0
|
||||
b23:b22 = (word)*a1++[12]
|
||||
b23:b22 = (word) *a1++[12]
|
||||
a4 = 2 ext a0 .. 0x1a
|
||||
a26 = 0x4988
|
||||
a4 = 0x12 .bitset a20 .. 0x12
|
||||
a13:a12 = (word)*-a18[a12]
|
||||
a13:a12 = (word) *-a18[a12]
|
||||
a17 = a31 avg a0
|
||||
b22 = (word)*+b14[0x3da6]
|
||||
a4 = (half)*+b15[0x49]
|
||||
b22 = (word) *+b14[0x3da6]
|
||||
a4 = (half) *+b15[0x49]
|
||||
a25 = 8 ext a21 .. 0x10
|
||||
a = a8 ~ a21
|
||||
a26 = a8 ~ a21
|
||||
a16 = a23 * a25
|
||||
b17 = (half)*+b15[0xd15]
|
||||
a16 = (half)*+b14[0x0]
|
||||
*+b15[0x6c41] = (word)b19
|
||||
b8 = (byte)*+b14[0x660f]
|
||||
b12 = (byte)*+b14[0x2e0f]
|
||||
b12 = (byte)*+b14[0x2e0f]
|
||||
b17 = (half) *+b15[0xd15]
|
||||
a16 = (half) *+b14[0x0]
|
||||
*+b15[0x6c41] = (word) b19
|
||||
b8 = (byte) *+b14[0x660f]
|
||||
b12 = (byte) *+b14[0x2e0f]
|
||||
b12 = (byte) *+b14[0x2e0f]
|
||||
a0 = 0x1a .bitset a20 .. 0x1a
|
||||
a22 = 9 .bitclear a17 .. 9
|
||||
a10 = 0xe ext a12 .. 0
|
||||
a7 = 0 ext a27 .. 0x10
|
||||
a22 = 0x18 ext a29 .. 8
|
||||
*+b14[0x488b] = (byte)b0
|
||||
*+b14[0x488b] = (byte) b0
|
||||
a14 = 1 ext a17 .. 4
|
||||
a17 = (byte)*a3--[10]
|
||||
a17 = (byte) *a3--[10]
|
||||
b16 = (half) -0x2c00
|
||||
b4 = (half)*+b15[0x488d]
|
||||
b4 = (half) *+b15[0x488d]
|
||||
a6 = (half) 1
|
||||
a30 = 0 ext a0 .. 0
|
||||
a23:a22 = 1 + a20:a19
|
||||
a20 = (half)*-a23[a18]
|
||||
a20 = (half) *-a23[a18]
|
||||
b8 += 0x2463
|
||||
*-a1[14] = (word)a17
|
||||
*-a1[14] = (word) a17
|
||||
a16 = 0x1a ext a0 .. 0x11
|
||||
a23 = 0x1c ext a16 .. 0x10
|
||||
*+b14[0x5b1] = (word)b26
|
||||
*+b14[0x5b1] = (word) b26
|
||||
a4 = 2 ext a0 .. 0x13
|
||||
b19 = 0x1a .bitset b30 .. 0x1a
|
||||
b9 = (half)*+b15[0xb05]
|
||||
b9 = (half) *+b15[0xb05]
|
||||
a10 = 0x10 ext a8 .. 0
|
||||
a26 = (byte)*-a5[15]
|
||||
a26 = (byte) *-a5[15]
|
||||
b0 = 2 .bitset b0 .. 2
|
||||
a30 = (word)*+b15[0x4883]
|
||||
*+b15[0x47c1] = (word)b17
|
||||
*+b15[0x7fff] = (word)b31
|
||||
a2 = (half)*+b15[0x0]
|
||||
a30 = (word) *+b15[0x4883]
|
||||
*+b15[0x47c1] = (word) b17
|
||||
*+b15[0x7fff] = (word) b31
|
||||
a2 = (half) *+b15[0x0]
|
||||
a16 = a17 * a29
|
||||
b0 = b18 + 4
|
||||
b16 = 2 == b22
|
||||
b30 = (word)*-a16[0]
|
||||
b30 = (word) *-a16[0]
|
||||
a0 = 0x10 ext a15 .. 0
|
||||
a2 = 8 ext a29 .. 0x18
|
||||
a23:a22 = (word)*-a1[12]
|
||||
a23:a22 = (word) *-a1[12]
|
||||
b4 = 2 .bitset b0 .. 2
|
||||
*+b14[0xd05] = (half)b17
|
||||
*+b14[0xd05] = (half) b17
|
||||
a14 = 8 ext a0 .. 0
|
||||
b11 = (half)*+b14[0x4948]
|
||||
a9 = (half)*+b15[0x4848]
|
||||
b11 = (half) *+b14[0x4948]
|
||||
a9 = (half) *+b15[0x4848]
|
||||
a17 = a24 * a29
|
||||
a1:a0 = a0 * a0
|
||||
a26 = a0 * a1
|
||||
b30 = (word)*-a7[24]
|
||||
b30 = (word) *-a7[24]
|
||||
a17 = 0x18 ext a2 .. 5
|
||||
a10 = 0x10 ext a8 .. 0
|
||||
a19 = (half)*+b15[0x5048]
|
||||
a19 = (half) *+b15[0x5048]
|
||||
a15 = a24 * a29
|
||||
a17 = 0xf ext a2 .. 0x11
|
||||
*a13--(a9) = (half)b27:b26
|
||||
*a13--(a9) = (half) b27:b26
|
||||
b2 = 5 * b0
|
||||
a0 = 0 ext a0 .. 0
|
||||
a22 = (half)*-a0[a2]
|
||||
a22 = (half) *-a0[a2]
|
||||
a30 = 6 ext a17 .. 2
|
||||
a4 = (half) 0x6381
|
||||
a24 = a0 * a1
|
||||
b13 = (byte)*+b14[0x1066]
|
||||
*a16++[10] = (half)a0
|
||||
b13 = (byte) *+b14[0x1066]
|
||||
*a16++[10] = (half) a0
|
||||
b19 += 0x13fc
|
||||
a17 = 0xe ext a2 .. 0x15
|
||||
a26 = 0xc * a3
|
||||
b0 = b2 * b0
|
||||
a24 = (byte)*+b14[0x508b]
|
||||
a24 = (byte) *+b14[0x508b]
|
||||
a28 = 0x10 ext a8 .. 0
|
||||
a18 = 1 ext a31 .. 4
|
||||
a17 = (byte)*a2--[9]
|
||||
a17 = (byte) *a2--[9]
|
||||
a26 = a1 * a17
|
||||
a28 = 1 ext a17 .. 4
|
||||
a17 = (byte)*a3--[10]
|
||||
a30 = (half)*a3++[24]
|
||||
a17 = (byte)*a3--[11]
|
||||
*+b14[0x488d] = (word)a16
|
||||
b8 = (half)*-a8[a2]
|
||||
a17 = (byte) *a3--[10]
|
||||
a30 = (half) *a3++[24]
|
||||
a17 = (byte) *a3--[11]
|
||||
*+b14[0x488d] = (word) a16
|
||||
b8 = (half) *-a8[a2]
|
||||
a18 = a1 * a17
|
||||
*+b15[0x63fc] = (word)b16
|
||||
*+a19[a4] = (half)a31:a30
|
||||
*-a1[14] = (word)a27
|
||||
a3 = (byte)*+b14[0x4039]
|
||||
b26 = (half)*+b14[0x2200]
|
||||
*+b15[0x63fc] = (word) b16
|
||||
*+a19[a4] = (half) a31:a30
|
||||
*-a1[14] = (word) a27
|
||||
a3 = (byte) *+b14[0x4039]
|
||||
b26 = (half) *+b14[0x2200]
|
||||
b11 = b2 * b16
|
||||
*+b14[0x505b] = (half)a8
|
||||
b2 = (half)*+b14[0x5ec3]
|
||||
*+b14[0x505b] = (half) a8
|
||||
b2 = (half) *+b14[0x5ec3]
|
||||
a8 = 0 ext a0 .. 0
|
||||
a14 = 0x10 ext a0 .. 0
|
||||
a19 = 0xa .bitset a26 .. 0xa
|
||||
*+b15[0x31c0] = (byte)b4
|
||||
*+b15[0x31c0] = (byte) b4
|
||||
a0 = (half) 1
|
||||
a14 = a24 * a0
|
||||
a17 += 0x788
|
||||
*+b14[0x405b] = (half)a3
|
||||
b3:b2 = (word)*+a23[22]
|
||||
b0 = (half)*+b14[0x662e]
|
||||
*+b14[0x405b] = (half) a3
|
||||
b3:b2 = (word) *+a23[22]
|
||||
b0 = (half) *+b14[0x662e]
|
||||
b0 = 0x1a .bitset b20 .. 0x1a
|
||||
a14 = 2 .bitset a4 .. 2
|
||||
b22 = b4 - b18
|
||||
a17 = 0x1b ext a2 .. 0x1f
|
||||
a3 = a18 * a20
|
||||
a31 = (half)*+a5[14]
|
||||
a31 = (half) *+a5[14]
|
||||
a3 = 9 .bitclear a18 .. 9
|
||||
a20 = 0 ext a0 .. 0
|
||||
b18 = max(b24, b16)
|
||||
*a3++[a24] = (half)a7:a6
|
||||
*-a0[2] = (word)b0
|
||||
*-a21[18] = (word)a2
|
||||
a2 = (half)*+b15[0x544c]
|
||||
*a3++[a24] = (half) a7:a6
|
||||
*-a0[2] = (word) b0
|
||||
*-a21[18] = (word) a2
|
||||
a2 = (half) *+b15[0x544c]
|
||||
a26 = a15 * a8
|
||||
a0 = 0xa ext a21 .. 0x13
|
||||
a19 = a2 * a31
|
||||
a0 = 0 ext a0 .. 0
|
||||
*+b15[0xf48] = (byte)b22
|
||||
a27 = (half)*+b15[0x4ccc]
|
||||
a25 = (half)*+b15[0x4ccc]
|
||||
*+b15[0xf48] = (byte) b22
|
||||
a27 = (half) *+b15[0x4ccc]
|
||||
a25 = (half) *+b15[0x4ccc]
|
||||
a19 = 0xf ext a2 .. 6
|
||||
a17 = 0xe ext a2 .. 8
|
||||
a7 = 0x10 ext a27 .. 1
|
||||
a15 = a25 - a26
|
||||
a20 = (half)*+b15[0x348]
|
||||
a20 = (half) *+b15[0x348]
|
||||
a16 = 0xe ext a0 .. 0
|
||||
a19 = (half)*-a16[a10]
|
||||
a2 = (half)*a3++[29]
|
||||
a19 = (half) *-a16[a10]
|
||||
a2 = (half) *a3++[29]
|
||||
a26 = 2 .bitset a0 .. 2
|
||||
a12 = 0xe ext a29 .. 0x18
|
||||
a12 = 5 .bitclear a5 .. 5
|
||||
a0 = (half)*+b14[0x0]
|
||||
a16 = (half)*+b14[0x29f0]
|
||||
*+b14[0x7f48] = (byte)a19
|
||||
a0 = (half) *+b14[0x0]
|
||||
a16 = (half) *+b14[0x29f0]
|
||||
*+b14[0x7f48] = (byte) a19
|
||||
a0 = 0 ext a0 .. 0
|
||||
b30 = b30 * b17
|
||||
a16 = 2 .bitset a2 .. 2
|
||||
|
|
|
|||
|
|
@ -360,34 +360,39 @@ RUN
|
|||
|
||||
NAME=v850 random pseudo
|
||||
FILE=bins/elf/ld-2.27.so
|
||||
BROKEN=1
|
||||
CMDS=<<EOF
|
||||
sd +128
|
||||
e asm.arch=v850
|
||||
e asm.parser=v850.pseudo
|
||||
e asm.pseudo=true
|
||||
b 64
|
||||
pi~=
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
r8[0x1047] = (byte) r24
|
||||
*(r8 + 0x1047) = (byte) r24
|
||||
r0 = r0
|
||||
r0 = r0
|
||||
r9 = ~r31
|
||||
r1 = ~r4
|
||||
r0 = r0
|
||||
r0 = r0
|
||||
r0 == 0xa
|
||||
r17 = 0x388 | r13
|
||||
r13 = 8
|
||||
r13 = 0
|
||||
r9 = r2
|
||||
r17 = r13 | 0x388
|
||||
r0 = r0
|
||||
r9 = r0
|
||||
r11 = (0x8548 << 16) + r26
|
||||
r2 == -0xc
|
||||
r9 = r3
|
||||
r9 = r3
|
||||
r3 = ~r4
|
||||
r11 = (0x8548 << XX) + r26
|
||||
r6 = r18 | 0
|
||||
r9 = r16
|
||||
r10 = r3 | 0
|
||||
r9 = r8
|
||||
r2 /= r19
|
||||
r9 /= r19
|
||||
r0 = r20
|
||||
r9 = r16
|
||||
r22 = r5 | 0
|
||||
r4 == -1
|
||||
r17 = r8 & 0
|
||||
r0 = ~r2
|
||||
r25 = (byte) *(r8805 + 0x5)
|
||||
r9 = r0
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ int main(int argc, char **argv) {
|
|||
printf("%s\n", str);
|
||||
printf("\n----\n\n");
|
||||
rz_parse_use(p, "att2intel");
|
||||
rz_parse_parse(p, "movl $3, %eax", str); //, sizeof (str));
|
||||
rz_parse_pseudocode(p, "movl $3, %eax", str); //, sizeof (str));
|
||||
//rz_parse_filter (p, NULL, "movl $3, %eax", str, sizeof (str));
|
||||
printf("%s\n", str);
|
||||
} else {
|
||||
|
|
@ -29,7 +29,7 @@ int main(int argc, char **argv) {
|
|||
break;
|
||||
buf[strlen(buf) - 1] = 0;
|
||||
if (*buf) {
|
||||
rz_parse_parse(p, buf, str); //, sizeof (str));
|
||||
rz_parse_pseudocode(p, buf, str); //, sizeof (str));
|
||||
printf("%s\n", str);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue