Add anal plugin for kvx architecture

KVX is VLIW architecture, kind of like a DSP, it can execute more than
one "instruction" per cycle. Each cycle a bundle of instruction is
executed which is comprised of up to 6 instructions. The general rules
for bundle are: only one BCU instruction (which comes first); only one
LSU instruction; and up to 4 ALU instructions (depending on the type).

In assembly the end of a bundle is marked by a `;;` in an empty line,
here in r2 (to make things more compact and readable) the end of bundle
is appended after the last instruction, but beware that this is not valid
kvx assembly.
This commit is contained in:
Jules Maselbas 2019-06-20 15:09:02 +02:00 committed by pancake
parent ba6c958c7b
commit 14731d6366
13 changed files with 1799 additions and 0 deletions

View File

@ -18,6 +18,7 @@ anal.h8300
anal.hexagon
anal.i8080
anal.java
anal.kvx
anal.m68k_cs
anal.m680x_cs
anal.xtensa

View File

@ -15,6 +15,7 @@ anal.h8300
anal.hexagon
anal.i8080
anal.java
anal.kvx
anal.m68k_cs
anal.m680x_cs
anal.xtensa

View File

@ -16,6 +16,7 @@ anal.h8300
anal.hexagon
anal.i8080
anal.java
anal.kvx
anal.xtensa
anal.malbolge
anal.mcore

View File

@ -12,6 +12,7 @@ anal.dalvik
anal.gb
anal.i8080
anal.java
anal.kvx
anal.m68k_cs
anal.malbolge
anal.mips_cs

View File

@ -0,0 +1,277 @@
/* radare - LGPL - Copyright 2022 - jmaselbas */
#include "kvx.h"
#include "kvx-reg.h"
#include <stdio.h>
#include <string.h>
#include <r_anal.h>
const opc_t kv3_opc[] = {
#include "kv3.opc"
};
#define KV3_OPC_COUNT R_ARRAY_SIZE(kv3_opc)
int kvx_instr_print(insn_t *insn, ut64 offset, char *buf, size_t len) {
const char *fmt = insn->opc->format;
operand_t opr;
int i = 0;
int n, w;
/* print mnemonic */
w = snprintf (buf, len, "%s%s", insn->opc->mnemonic, fmt[0] != '\0' ? " " : "");
n = R_MIN (w, len);
/* append operands */
while (n < (len - 1) && *fmt != '\0') {
if (fmt[0] == '%' && fmt[1] == 's') {
/* decode each operand in order */
if (i < R_ARRAY_SIZE (insn->opc->decode) && insn->opc->decode[i]) {
insn->opc->decode[i] (&opr, insn->value);
if (opr.type == KVX_OPER_TYPE_IMM)
w = snprintf (buf + n, len - n, "0x%lx", opr.imm);
else if (opr.type == KVX_OPER_TYPE_OFF)
w = snprintf (buf + n, len - n, "0x%lx", opr.imm + offset);
else if (opr.type == KVX_OPER_TYPE_REG)
w = snprintf (buf + n, len - n, "%s", opr.reg);
else
w = 0;
n += R_MIN (w, len - n);
i++;
/* advance after the format '%s' */
fmt += 2;
}
} else {
/* simple copy */
buf[n] = fmt[0];
fmt++;
n++;
}
}
if (!insn->rem) {
w = snprintf (buf + n, len - n, " ;;");
n += R_MIN (w, len - n);
}
buf[n] = 0;
return n;
}
ut64 kvx_instr_jump(insn_t *insn, ut64 offset) {
operand_t opr;
int i;
for (i = 0; i < 4 && insn->opc->decode[i]; i++) {
insn->opc->decode[i] (&opr, insn->value);
if (opr.type == KVX_OPER_TYPE_OFF) {
return opr.imm + offset;
}
}
return offset;
}
static const int immx_to_bundle_issue[] = {
[IMMX_ISSUE_ALU0] = BUNDLE_ISSUE_ALU0,
[IMMX_ISSUE_ALU1] = BUNDLE_ISSUE_ALU1,
[IMMX_ISSUE_MAU] = BUNDLE_ISSUE_MAU,
[IMMX_ISSUE_LSU] = BUNDLE_ISSUE_LSU,
};
static inline int kvx_steering(ut32 x) {
return (((x) & 0x60000000) >> 29);
}
static inline int kvx_extension(ut32 x) {
return (((x) & 0x18000000) >> 27);
}
static inline int kvx_has_parallel_bit(ut32 x) {
return (((x) & 0x80000000) == 0x80000000);
}
static inline int kvx_is_tca_opcode(ut32 x) {
unsigned major = ((x)>>24) & 0x1F;
return (major > 1) && (major < 8);
}
static inline int kvx_is_nop_opcode(ut32 x) {
return ((x)<<1) == 0xFFFFFFFE;
}
static inline int kvx_opc_match(const opc_t *opc, insn_t *insn) {
int i;
if (opc->len != insn->len)
return 0;
for (i = 0; i < insn->len; i++) {
if ((insn->value[i] & opc->mask[i]) != opc->value[i])
return 0;
}
return 1;
}
static int disassemble_bundle(bundle_t *bundle, const ut32 *words, int count) {
bool used[KVX_MAX_BUNDLE_ISSUE] = {0};
insn_t *insn;
ut32 word;
int issue, immx, extension;
int bcu = 0;
int i;
for (i = 0; i < count; i++) {
extension = 0;
word = words[i];
switch (kvx_steering (word)) {
case STEERING_BCU:
if (i == 0 && !kvx_is_tca_opcode (word)) {
bcu = 1;
issue = BUNDLE_ISSUE_BCU;
} else if ((i == 0 && kvx_is_tca_opcode (word))
|| (i == 1 && bcu && kvx_is_tca_opcode (word))) {
issue = BUNDLE_ISSUE_TCA;
} else {
immx = kvx_extension (word);
issue = immx_to_bundle_issue[immx];
extension = 1;
}
break;
case STEERING_ALU:
if (!used[BUNDLE_ISSUE_ALU0]) {
issue = BUNDLE_ISSUE_ALU0;
} else if (!used[BUNDLE_ISSUE_ALU1]) {
issue = BUNDLE_ISSUE_ALU1;
} else if (!used[BUNDLE_ISSUE_MAU]) {
issue = BUNDLE_ISSUE_MAU;
} else if (!used[BUNDLE_ISSUE_LSU]) {
issue = BUNDLE_ISSUE_LSU;
} else {
/* too many ALUs */
goto error;
}
break;
case STEERING_MAU:
issue = BUNDLE_ISSUE_MAU;
break;
case STEERING_LSU:
issue = BUNDLE_ISSUE_LSU;
break;
}
insn = &bundle->issue[issue];
if (!used[issue]) {
used[issue] = 1;
insn->len = 0;
} else if (!extension && used[issue]) {
/* issue already used */
goto error;
} else if (extension && !used[issue]) {
/* missing issue */
goto error;
}
if (insn->len == KVX_MAX_SYLLABLES) {
/* too many syllables */
goto error;
}
insn->value[insn->len] = word;
insn->len++;
}
for (issue = 0; issue < KVX_MAX_BUNDLE_ISSUE; issue++) {
if (!used[issue])
continue;
insn = &bundle->issue[issue];
insn->opc = NULL;
for (i = 0; i < KV3_OPC_COUNT; i++) {
if (kvx_opc_match (&kv3_opc[i], insn)) {
insn->opc = &kv3_opc[i];
break;
}
}
}
count = 0;
for (issue = KVX_MAX_BUNDLE_ISSUE - 1; issue >= 0; issue--) {
if (!used[issue])
continue;
insn = &bundle->issue[issue];
insn->rem = count++;
}
return 0;
error:
return -1;
}
static int read_bundle(ut32 *words, const ut8 *buf, int len) {
int count = 0;
ut32 word;
while (len >= sizeof (ut32) && count < KVX_MAX_BUNDLE_WORDS) {
word = r_read_le32 (buf);
words[count] = word;
count++;
if (!kvx_has_parallel_bit (word)) {
break;
}
buf += sizeof (ut32);
len -= sizeof (ut32);
}
if (count == KVX_MAX_BUNDLE_WORDS && kvx_has_parallel_bit (word)) {
/* this is wrong */
}
return count;
}
insn_t *kvx_next_insn(bundle_t *bundle, ut64 addr, const ut8 *buf, int len) {
ut32 words[KVX_MAX_BUNDLE_WORDS];
ut64 start;
int count, issue = KVX_MAX_BUNDLE_ISSUE;
int ret;
if (bundle->addr <= addr && addr < (bundle->addr + bundle->size)) {
start = bundle->addr;
issue = 0;
for (issue = 0; issue < KVX_MAX_BUNDLE_ISSUE; issue++) {
if (addr == start) {
break;
}
start += bundle->issue[issue].len * sizeof (ut32);
}
while (issue < KVX_MAX_BUNDLE_ISSUE && bundle->issue[issue].len == 0) {
issue++;
}
}
if (issue == KVX_MAX_BUNDLE_ISSUE) {
memset (bundle, 0, sizeof (*bundle));
issue = 0;
count = read_bundle (words, buf, len);
if (count == 0)
return NULL;
bundle->addr = addr;
bundle->size = count * sizeof (ut32);
ret = disassemble_bundle (bundle, words, count);
if (ret)
return NULL;
}
while (issue < KVX_MAX_BUNDLE_ISSUE && bundle->issue[issue].len == 0) {
issue++;
}
if (issue < KVX_MAX_BUNDLE_ISSUE) {
return &bundle->issue[issue];
}
return NULL;
}

1066
libr/anal/arch/kvx/kvx-reg.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
void kvx_decode_none(operand_t *, const ut32 *);
void kv3_decode_rw(operand_t *, const ut32 *);
void kv3_decode_ry(operand_t *, const ut32 *);
void kv3_decode_rz(operand_t *, const ut32 *);
void kv3_decode_ra(operand_t *, const ut32 *);
void kv3_decode_rap(operand_t *, const ut32 *);
void kv3_decode_raq(operand_t *, const ut32 *);
void kv3_decode_rb(operand_t *, const ut32 *);
void kv3_decode_rb_odd(operand_t *, const ut32 *);
void kv3_decode_rb_even(operand_t *, const ut32 *);
void kv3_decode_rbp(operand_t *, const ut32 *);
void kv3_decode_rbq(operand_t *, const ut32 *);
void kv3_decode_rc(operand_t *, const ut32 *);
void kv3_decode_rc_odd(operand_t *, const ut32 *);
void kv3_decode_rc_even(operand_t *, const ut32 *);
void kv3_decode_rd(operand_t *, const ut32 *);
void kv3_decode_rn(operand_t *, const ut32 *);
void kv3_decode_rm(operand_t *, const ut32 *);
void kv3_decode_u6(operand_t *, const ut32 *);
void kv3_decode_s10(operand_t *, const ut32 *);
void kv3_decode_s16(operand_t *, const ut32 *);
void kv3_decode_sys(operand_t *, const ut32 *);
void kv3_decode_imm32(operand_t *, const ut32 *);
void kv3_decode_imm37(operand_t *, const ut32 *);
void kv3_decode_imm43(operand_t *, const ut32 *);
void kv3_decode_imm64(operand_t *, const ut32 *);
void kv3_decode_off27(operand_t *, const ut32 *);
void kv3_decode_off54(operand_t *, const ut32 *);
void kv3_decode_pcrel17(operand_t *, const ut32 *);
void kv3_decode_pcrel27(operand_t *, const ut32 *);
void kv3_decode_shift(operand_t *, const ut32 *);
void kv3_decode_start_bit(operand_t *, const ut32 *);
void kv3_decode_stop_bit(operand_t *, const ut32 *);
void kv3_decode_ru(operand_t *, const ut32 *);
void kv3_decode_rt(operand_t *, const ut32 *);
void kv3_decode_rbq(operand_t *, const ut32 *);
void kv3_decode_rq(operand_t *, const ut32 *);
void kv3_decode_rp(operand_t *, const ut32 *);
void kv3_decode_ro(operand_t *, const ut32 *);
void kv3_decode_rs(operand_t *, const ut32 *);
void kv3_decode_rv(operand_t *, const ut32 *);
void kv3_decode_rr(operand_t *, const ut32 *);
void kv3_decode_re(operand_t *, const ut32 *);

68
libr/anal/arch/kvx/kvx.h Normal file
View File

@ -0,0 +1,68 @@
/* TODO: <LICENSE INFO HERE> */
#ifndef ASM_KVX_H
#define ASM_KVX_H
#include <stdint.h>
#include <r_types.h>
#define KVX_MAX_SYLLABLES 3
#define KVX_MAX_OPERANDS 7
#define KVX_MAX_BUNDLE_ISSUE 6
#define KVX_MAX_BUNDLE_WORDS 8
#define BUNDLE_ISSUE_BCU 0
#define BUNDLE_ISSUE_TCA 1
#define BUNDLE_ISSUE_ALU0 2
#define BUNDLE_ISSUE_ALU1 3
#define BUNDLE_ISSUE_MAU 4
#define BUNDLE_ISSUE_LSU 5
#define STEERING_BCU 0
#define STEERING_LSU 1
#define STEERING_MAU 2
#define STEERING_ALU 3
#define IMMX_ISSUE_ALU0 0
#define IMMX_ISSUE_ALU1 1
#define IMMX_ISSUE_MAU 2
#define IMMX_ISSUE_LSU 3
typedef struct {
int type;
#define KVX_OPER_TYPE_UNK 0
#define KVX_OPER_TYPE_REG 1
#define KVX_OPER_TYPE_IMM 2
#define KVX_OPER_TYPE_OFF 3
char *reg;
ut64 imm;
} operand_t;
typedef struct {
const char *mnemonic;
const char *format;
int len;
ut32 mask[KVX_MAX_SYLLABLES];
ut32 value[KVX_MAX_SYLLABLES];
void (*decode[4])(operand_t *, const ut32 *);
ut32 type;
ut32 cond;
} opc_t;
typedef struct {
const opc_t *opc;
int rem;
int len;
ut32 value[KVX_MAX_SYLLABLES];
} insn_t;
typedef struct {
ut64 addr;
int size;
insn_t issue[KVX_MAX_BUNDLE_ISSUE];
} bundle_t;
int kvx_instr_print(insn_t *insn, ut64 offset, char *buf, size_t len);
ut64 kvx_instr_jump(insn_t *insn, ut64 offset);
insn_t *kvx_next_insn(bundle_t *bundle, ut64 addr, const ut8 *buf, int len);
#endif

View File

@ -62,6 +62,7 @@ r_anal_sources = [
join_paths('p','anal_i4004.c'),
join_paths('p','anal_i8080.c'),
join_paths('p','anal_java.c'),
join_paths('p','anal_kvx.c'),
join_paths('p','anal_m680x_cs.c'),
join_paths('p','anal_m68k_cs.c'),
join_paths('p','anal_malbolge.c'),
@ -108,6 +109,8 @@ r_anal_sources = [
join_paths('arch','hexagon','hexagon.c'),
join_paths('arch','hexagon','hexagon_anal.c'),
join_paths('arch','hexagon','hexagon_disas.c'),
join_paths('arch','kvx','kvx-dis.c'),
join_paths('arch','kvx','kvx-reg.c'),
join_paths('arch','loongarch','gnu','loongarch-coder.c'),
join_paths('arch','loongarch','gnu','loongarch-dis.c'),
join_paths('arch','loongarch','gnu','loongarch-opc.c'),
@ -146,6 +149,7 @@ r_anal_sources = [
]
incdirs = [
'arch/gb',
'arch/kvx',
'arch/hexagon'
]

322
libr/anal/p/anal_kvx.c Normal file
View File

@ -0,0 +1,322 @@
/* radare - LGPL - Copyright 2022 - jmaselbas */
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_anal.h>
#include "kvx.h"
const char *kvx_reg_profile = ""
"=PC pc\n"
"=SP r12\n"
"=LR ra\n"
"=SN r0\n"
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
"=A3 r3\n"
"=A4 r4\n"
"=A5 r5\n"
"=A6 r6\n"
"=A7 r7\n"
"=A8 r8\n"
"=A9 r9\n"
/* FIXME: alias of three char are not supported */
#if 0
"=A10 r10\n"
"=A11 r11\n"
#endif
"=R0 r0\n"
"gpr r0 .64 0 0\n"
"gpr r1 .64 8 0\n"
"gpr r2 .64 16 0\n"
"gpr r3 .64 24 0\n"
"gpr r4 .64 32 0\n"
"gpr r5 .64 40 0\n"
"gpr r6 .64 48 0\n"
"gpr r7 .64 56 0\n"
"gpr r8 .64 64 0\n"
"gpr r9 .64 72 0\n"
"gpr r10 .64 80 0\n"
"gpr r11 .64 88 0\n"
"gpr r12 .64 96 0\n"
"gpr r13 .64 104 0\n"
"gpr r14 .64 112 0\n"
"gpr r15 .64 120 0\n"
"gpr r16 .64 128 0\n"
"gpr r17 .64 136 0\n"
"gpr r18 .64 144 0\n"
"gpr r19 .64 152 0\n"
"gpr r20 .64 160 0\n"
"gpr r21 .64 168 0\n"
"gpr r22 .64 176 0\n"
"gpr r23 .64 184 0\n"
"gpr r24 .64 192 0\n"
"gpr r25 .64 200 0\n"
"gpr r26 .64 208 0\n"
"gpr r27 .64 216 0\n"
"gpr r28 .64 224 0\n"
"gpr r29 .64 232 0\n"
"gpr r30 .64 240 0\n"
"gpr r31 .64 248 0\n"
"gpr r32 .64 256 0\n"
"gpr r33 .64 264 0\n"
"gpr r34 .64 272 0\n"
"gpr r35 .64 280 0\n"
"gpr r36 .64 288 0\n"
"gpr r37 .64 296 0\n"
"gpr r38 .64 304 0\n"
"gpr r39 .64 312 0\n"
"gpr r40 .64 320 0\n"
"gpr r41 .64 328 0\n"
"gpr r42 .64 336 0\n"
"gpr r43 .64 344 0\n"
"gpr r44 .64 352 0\n"
"gpr r45 .64 360 0\n"
"gpr r46 .64 368 0\n"
"gpr r47 .64 376 0\n"
"gpr r48 .64 384 0\n"
"gpr r49 .64 392 0\n"
"gpr r50 .64 400 0\n"
"gpr r51 .64 408 0\n"
"gpr r52 .64 416 0\n"
"gpr r53 .64 424 0\n"
"gpr r54 .64 432 0\n"
"gpr r55 .64 440 0\n"
"gpr r56 .64 448 0\n"
"gpr r57 .64 456 0\n"
"gpr r58 .64 464 0\n"
"gpr r59 .64 472 0\n"
"gpr r60 .64 480 0\n"
"gpr r61 .64 488 0\n"
"gpr r62 .64 496 0\n"
"gpr r63 .64 504 0\n"
"gpr r0r1 .128 0 0\n"
"gpr r2r3 .128 16 0\n"
"gpr r4r5 .128 32 0\n"
"gpr r6r7 .128 48 0\n"
"gpr r8r9 .128 64 0\n"
"gpr r10r11 .128 80 0\n"
"gpr r12r13 .128 96 0\n"
"gpr r14r15 .128 112 0\n"
"gpr r16r17 .128 128 0\n"
"gpr r18r19 .128 144 0\n"
"gpr r20r21 .128 160 0\n"
"gpr r22r23 .128 176 0\n"
"gpr r24r25 .128 192 0\n"
"gpr r26r27 .128 208 0\n"
"gpr r28r29 .128 224 0\n"
"gpr r30r31 .128 240 0\n"
"gpr r32r33 .128 256 0\n"
"gpr r34r35 .128 272 0\n"
"gpr r36r37 .128 288 0\n"
"gpr r38r39 .128 304 0\n"
"gpr r40r41 .128 320 0\n"
"gpr r42r43 .128 336 0\n"
"gpr r44r45 .128 352 0\n"
"gpr r46r47 .128 368 0\n"
"gpr r48r49 .128 384 0\n"
"gpr r50r51 .128 400 0\n"
"gpr r52r53 .128 416 0\n"
"gpr r54r55 .128 432 0\n"
"gpr r56r57 .128 448 0\n"
"gpr r58r59 .128 464 0\n"
"gpr r60r61 .128 480 0\n"
"gpr r62r63 .128 496 0\n"
"gpr r0r1r2r3 .256 0 0\n"
"gpr r4r5r6r7 .256 32 0\n"
"gpr r8r9r10r11 .256 64 0\n"
"gpr r12r13r14r15 .256 96 0\n"
"gpr r16r17r18r19 .256 128 0\n"
"gpr r20r21r22r23 .256 160 0\n"
"gpr r24r25r26r27 .256 192 0\n"
"gpr r28r29r30r31 .256 224 0\n"
"gpr r32r33r34r35 .256 256 0\n"
"gpr r36r37r38r39 .256 288 0\n"
"gpr r40r41r42r43 .256 320 0\n"
"gpr r44r45r46r47 .256 352 0\n"
"gpr r48r49r50r51 .256 384 0\n"
"gpr r52r53r54r55 .256 416 0\n"
"gpr r56r57r58r59 .256 448 0\n"
"gpr r60r61r62r63 .256 480 0\n"
"gpr pc .64 512 0\n"
"gpr ps .64 520 0\n"
"gpr pcr .64 528 0\n"
"gpr ra .64 536 0\n"
"gpr cs .64 544 0\n"
"gpr csit .64 552 0\n"
"gpr aespc .64 560 0\n"
"gpr ls .64 568 0\n"
"gpr le .64 576 0\n"
"gpr lc .64 584 0\n"
"gpr ipe .64 592 0\n"
"gpr men .64 600 0\n"
"gpr pmc .64 608 0\n"
"gpr pm0 .64 616 0\n"
"gpr pm1 .64 624 0\n"
"gpr pm2 .64 632 0\n"
"gpr pm3 .64 640 0\n"
"gpr pmsa .64 648 0\n"
"gpr tcr .64 656 0\n"
"gpr t0v .64 664 0\n"
"gpr t1v .64 672 0\n"
"gpr t0r .64 680 0\n"
"gpr t1r .64 688 0\n"
"gpr wdv .64 696 0\n"
"gpr wdr .64 704 0\n"
"gpr ile .64 712 0\n"
"gpr ill .64 720 0\n"
"gpr ilr .64 728 0\n"
"gpr mmc .64 736 0\n"
"gpr tel .64 744 0\n"
"gpr teh .64 752 0\n"
"gpr syo .64 768 0\n"
"gpr hto .64 776 0\n"
"gpr ito .64 784 0\n"
"gpr do .64 792 0\n"
"gpr mo .64 800 0\n"
"gpr pso .64 808 0\n"
"gpr dc .64 832 0\n"
"gpr dba0 .64 840 0\n"
"gpr dba1 .64 848 0\n"
"gpr dwa0 .64 856 0\n"
"gpr dwa1 .64 864 0\n"
"gpr mes .64 872 0\n"
"gpr ws .64 880 0\n"
"gpr spc_pl0 .64 1024 0\n"
"gpr spc_pl1 .64 1032 0\n"
"gpr spc_pl2 .64 1040 0\n"
"gpr spc_pl3 .64 1048 0\n"
"gpr sps_pl0 .64 1056 0\n"
"gpr sps_pl1 .64 1064 0\n"
"gpr sps_pl2 .64 1072 0\n"
"gpr sps_pl3 .64 1080 0\n"
"gpr ea_pl0 .64 1088 0\n"
"gpr ea_pl1 .64 1096 0\n"
"gpr ea_pl2 .64 1104 0\n"
"gpr ea_pl3 .64 1112 0\n"
"gpr ev_pl0 .64 1120 0\n"
"gpr ev_pl1 .64 1128 0\n"
"gpr ev_pl2 .64 1136 0\n"
"gpr ev_pl3 .64 1144 0\n"
"gpr sr_pl0 .64 1152 0\n"
"gpr sr_pl1 .64 1160 0\n"
"gpr sr_pl2 .64 1168 0\n"
"gpr sr_pl3 .64 1176 0\n"
"gpr es_pl0 .64 1184 0\n"
"gpr es_pl1 .64 1192 0\n"
"gpr es_pl2 .64 1200 0\n"
"gpr es_pl3 .64 1208 0\n"
"gpr syow .64 1280 0\n"
"gpr htow .64 1288 0\n"
"gpr itow .64 1296 0\n"
"gpr dow .64 1304 0\n"
"gpr mow .64 1312 0\n"
"gpr psow .64 1320 0\n"
"gpr spc .64 1536 0\n"
"gpr sps .64 1568 0\n"
"gpr ea .64 1600 0\n"
"gpr ev .64 1632 0\n"
"gpr sr .64 1664 0\n"
"gpr es .64 1696 0\n"
;
/* The bundle store several instruction that cannot be disassembled
* individually, but each instructions should be printed on it's own
* line for readability. The function kvx_next_insn does all the magic
* of figuring out if the next instruction is already decoded in this
* bundle or if it needs to decode a new bundle */
static R_TH_LOCAL bundle_t bundle;
static int kvx_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len, RAnalOpMask mask) {
char strasm[64];
r_return_val_if_fail (anal && op, -1);
if (addr % 4) {
goto unaligned;
}
insn_t *insn = kvx_next_insn (&bundle, addr, b, len);
if (!insn) {
goto invalid;
}
op->addr = addr;
op->size = insn->len * sizeof (ut32);
if (insn->opc) {
if (mask & R_ANAL_OP_MASK_DISASM) {
kvx_instr_print (insn, addr, strasm, sizeof (strasm));
op->mnemonic = strdup (strasm);
}
op->type = insn->opc->type;
op->cond = insn->opc->cond;
/* The delay slot is a bit abused here, it is used make each
* instructions in a bundle complet at the same address, for
* exemple branch isntruction comes first but will be effective
* at the end of the bundle, after the remaning instructions. */
op->delay = insn->rem;
if ((op->type & R_ANAL_OP_TYPE_CJMP) == R_ANAL_OP_TYPE_CJMP) {
/* if fail goto next bundle */
op->fail = bundle.addr + bundle.size;
}
if ((op->type & R_ANAL_OP_TYPE_JMP) == R_ANAL_OP_TYPE_JMP) {
op->jump = kvx_instr_jump (insn, addr);
}
if ((op->type & R_ANAL_OP_TYPE_RET) == R_ANAL_OP_TYPE_RET) {
op->eob = true;
}
} else {
op->type = R_ANAL_OP_TYPE_UNK;
}
return op->size;
invalid:
op->size = 4;
return op->size;
unaligned:
op->size = 4 - (addr % 4);
return op->size;
}
static int kvx_archinfo(RAnal *anal, int query) {
switch (query) {
case R_ANAL_ARCHINFO_MIN_OP_SIZE:
return 4;
case R_ANAL_ARCHINFO_MAX_OP_SIZE:
return 12;
case R_ANAL_ARCHINFO_ALIGN:
return 4;
case R_ANAL_ARCHINFO_DATA_ALIGN:
return 0;
default:
return 0;
}
}
static bool kvx_set_reg_profile(RAnal *anal) {
return r_reg_set_profile_string (anal->reg, kvx_reg_profile);
}
RAnalPlugin r_anal_plugin_kvx = {
.name = "kvx",
.desc = "Kalray VLIW core analysis plugin",
.arch = "kvx",
.license = "GPL",
.esil = false,
.bits = 32|64,
.op = kvx_op,
.archinfo = kvx_archinfo,
.set_reg_profile = kvx_set_reg_profile,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_kvx,
.version = R2_VERSION
};
#endif

13
libr/anal/p/kvx.mk Normal file
View File

@ -0,0 +1,13 @@
OBJ_KVX=anal_kvx.o
OBJ_KVX+=../arch/kvx/kvx-dis.o ../arch/kvx/kvx-reg.o
CFLAGS+=-Iarch/kvx
STATIC_OBJ+=$(OBJ_KVX)
TARGET_KVX=anal_kvx.$(EXT_SO)
ifeq ($(WITHPIC),1)
ALL_TARGETS+=$(TARGET_KVX)
$(TARGET_KVX): $(OBJ_KVX)
${CC} $(call libname,anal_kvx) ${LDFLAGS} ${CFLAGS} -o $(TARGET_KVX) $(OBJ_KVX)
endif

View File

@ -2215,6 +2215,7 @@ extern RAnalPlugin r_anal_plugin_hexagon;
extern RAnalPlugin r_anal_plugin_i4004;
extern RAnalPlugin r_anal_plugin_i8080;
extern RAnalPlugin r_anal_plugin_java;
extern RAnalPlugin r_anal_plugin_kvx;
extern RAnalPlugin r_anal_plugin_m68k_cs;
extern RAnalPlugin r_anal_plugin_m680x_cs;
extern RAnalPlugin r_anal_plugin_malbolge;

View File

@ -144,6 +144,7 @@ anal_plugins += [
'i4004',
'i8080',
'java',
'kvx',
'm68k_cs',
'm680x_cs',
'malbolge',