mirror of
https://github.com/radareorg/radare2.git
synced 2024-10-08 19:33:31 +00:00
msp430: Initial commit
This commit is contained in:
parent
c3461856e2
commit
2b0009b858
@ -10,7 +10,7 @@ all: ${ALL_TARGETS} ;
|
||||
|
||||
ALL_TARGETS=
|
||||
# TODO: rename to enabled plugins
|
||||
ARCHS=x86_udis.mk ppc.mk arm_gnu.mk avr.mk csr.mk dalvik.mk sh.mk ebc.mk gb.mk malbolge.mk ws.mk h8300.mk cr16.mk v850.mk
|
||||
ARCHS=x86_udis.mk ppc.mk arm_gnu.mk avr.mk csr.mk dalvik.mk sh.mk ebc.mk gb.mk malbolge.mk ws.mk h8300.mk cr16.mk v850.mk msp430.mk
|
||||
include $(ARCHS)
|
||||
|
||||
clean:
|
||||
|
88
libr/anal/p/anal_msp430.c
Normal file
88
libr/anal/p/anal_msp430.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_anal.h>
|
||||
#include <r_util.h>
|
||||
|
||||
#include <msp430_disas.h>
|
||||
|
||||
static int msp430_op(RAnal *anal, RAnalOp *op, ut64 addr,
|
||||
const ut8 *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
struct msp430_cmd cmd;
|
||||
|
||||
memset (&cmd, 0, sizeof (cmd));
|
||||
memset (op, 0, sizeof (RAnalOp));
|
||||
|
||||
ret = op->size = msp430_decode_command (buf, &cmd);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
op->addr = addr;
|
||||
op->jump = op->fail = UT64_MAX;
|
||||
op->ptr = op->val = -1;
|
||||
|
||||
switch (cmd.type) {
|
||||
case MSP430_ONEOP:
|
||||
switch (cmd.opcode) {
|
||||
case MSP430_RRA:
|
||||
case MSP430_RCR:
|
||||
op->type = R_ANAL_OP_TYPE_ROR; break;
|
||||
case MSP430_PUSH:
|
||||
op->type = R_ANAL_OP_TYPE_PUSH; break;
|
||||
case MSP430_CALL:
|
||||
op->type = R_ANAL_OP_TYPE_CALL; break;
|
||||
case MSP430_RETI:
|
||||
op->type = R_ANAL_OP_TYPE_RET; break;
|
||||
}
|
||||
break;
|
||||
case MSP430_TWOOP:
|
||||
case MSP430_BIT:
|
||||
case MSP430_BIC:
|
||||
case MSP430_BIS:
|
||||
case MSP430_MOV: op->type = R_ANAL_OP_TYPE_MOV; break;
|
||||
case MSP430_DADD:
|
||||
case MSP430_ADDC:
|
||||
case MSP430_ADD: op->type = R_ANAL_OP_TYPE_ADD; break;
|
||||
case MSP430_SUBC:
|
||||
case MSP430_SUB: op->type = R_ANAL_OP_TYPE_SUB; break;
|
||||
case MSP430_CMP: op->type = R_ANAL_OP_TYPE_CMP; break;
|
||||
case MSP430_XOR: op->type = R_ANAL_OP_TYPE_XOR; break;
|
||||
case MSP430_AND: op->type = R_ANAL_OP_TYPE_AND; break;
|
||||
break;
|
||||
case MSP430_JUMP:
|
||||
if (cmd.jmp_cond == MSP430_JMP) {
|
||||
op->type = R_ANAL_OP_TYPE_JMP;
|
||||
} else {
|
||||
op->type = R_ANAL_OP_TYPE_CJMP;
|
||||
}
|
||||
op->jump = addr + cmd.jmp_addr;
|
||||
op->fail = addr + 2;
|
||||
break;
|
||||
default:
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct r_anal_plugin_t r_anal_plugin_msp430 = {
|
||||
.name = "msp430",
|
||||
.desc = "TI MSP430 code analysis plugin",
|
||||
.license = "LGPL3",
|
||||
.arch = R_SYS_ARCH_MSP430,
|
||||
.bits = 16,
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.op = msp430_op,
|
||||
.set_reg_profile = NULL,
|
||||
.fingerprint_bb = NULL,
|
||||
.fingerprint_fcn = NULL,
|
||||
.diff_bb = NULL,
|
||||
.diff_fcn = NULL,
|
||||
.diff_eval = NULL,
|
||||
};
|
12
libr/anal/p/msp430.mk
Normal file
12
libr/anal/p/msp430.mk
Normal file
@ -0,0 +1,12 @@
|
||||
OBJ_msp430=anal_msp430.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_msp430}
|
||||
OBJ_msp430+=../../asm/arch/msp430/msp430_disas.o
|
||||
TARGET_msp430=anal_msp430.${EXT_SO}
|
||||
|
||||
ALL_TARGETS+=${TARGET_msp430}
|
||||
|
||||
${TARGET_msp430}: ${OBJ_msp430} ${SHARED_OBJ}
|
||||
$(call pwd)
|
||||
${CC} $(call libname,anal_msp430) ${CFLAGS} \
|
||||
-I../../include/ -o ${TARGET_msp430} ${OBJ_msp430}
|
508
libr/asm/arch/msp430/msp430_disas.c
Normal file
508
libr/asm/arch/msp430/msp430_disas.c
Normal file
@ -0,0 +1,508 @@
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
|
||||
#include "msp430_disas.h"
|
||||
|
||||
static const char *two_op_instrs[] = {
|
||||
[MSP430_MOV] = "mov",
|
||||
[MSP430_ADD] = "add",
|
||||
[MSP430_ADDC] = "addc",
|
||||
[MSP430_SUBC] = "subc",
|
||||
[MSP430_SUB] = "sub",
|
||||
[MSP430_CMP] = "cmp",
|
||||
[MSP430_DADD] = "dadd",
|
||||
[MSP430_BIT] = "bit",
|
||||
[MSP430_BIC] = "bic",
|
||||
[MSP430_BIS] = "bis",
|
||||
[MSP430_XOR] = "xor",
|
||||
[MSP430_AND] = "and",
|
||||
};
|
||||
|
||||
static const char *one_op_instrs[] = {
|
||||
[MSP430_RCR] = "rcr",
|
||||
[MSP430_SWPB] = "swpb",
|
||||
[MSP430_RRA] = "rra",
|
||||
[MSP430_SXT] = "sxt",
|
||||
[MSP430_PUSH] = "push",
|
||||
[MSP430_CALL] = "call",
|
||||
[MSP430_RETI] = "reti",
|
||||
};
|
||||
|
||||
static const char *jmp_instrs[] = {
|
||||
[MSP430_JEQ] = "jeq",
|
||||
[MSP430_JNE] = "jnz",
|
||||
[MSP430_JC] = "jc",
|
||||
[MSP430_JNC] = "jnc",
|
||||
[MSP430_JN] = "jn",
|
||||
[MSP430_JGE] = "jge",
|
||||
[MSP430_JL] = "jl",
|
||||
[MSP430_JMP] = "jmp",
|
||||
};
|
||||
|
||||
static ut8 get_twoop_opcode(ut16 instr)
|
||||
{
|
||||
return instr >> 12;
|
||||
}
|
||||
|
||||
static ut8 get_as(ut16 instr)
|
||||
{
|
||||
return (instr >> 4) & 3;
|
||||
}
|
||||
|
||||
static ut8 get_bw(ut16 instr)
|
||||
{
|
||||
return (instr >> 6) & 1;
|
||||
}
|
||||
|
||||
static ut8 get_ad(ut16 instr)
|
||||
{
|
||||
return (instr >> 7) & 1;
|
||||
}
|
||||
|
||||
static int get_src (instr) {
|
||||
return (instr >> 8) & 0xF;
|
||||
}
|
||||
|
||||
static int get_dst (instr) {
|
||||
return instr & 0xF;
|
||||
}
|
||||
|
||||
static void remove_first_operand (struct msp430_cmd *cmd)
|
||||
{
|
||||
if (strchr (cmd->operands, ',')) {
|
||||
memmove (cmd->operands, strchr (cmd->operands, ',') + 2,
|
||||
strlen (strchr (cmd->operands, ',') + 2) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_second_operand (struct msp430_cmd *cmd)
|
||||
{
|
||||
if (strchr (cmd->operands, ','))
|
||||
*strchr (cmd->operands, ',') = '\0';
|
||||
}
|
||||
|
||||
/* TODO: This is ugly as hell */
|
||||
static int decode_emulation (ut16 instr, ut16 dst, struct msp430_cmd *cmd)
|
||||
{
|
||||
int ret = -1;
|
||||
ut8 as, opcode;
|
||||
|
||||
as = get_as (instr);
|
||||
opcode = get_twoop_opcode (instr);
|
||||
|
||||
if (as == 0 && get_src (instr) == MSP430_R3 && opcode == MSP430_ADDC) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "adc.b" : "adc");
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#0, r%d",
|
||||
get_dst (instr));
|
||||
} else if (opcode == MSP430_MOV && as == 0 && get_src (instr) == MSP430_R3
|
||||
&& get_dst (instr) != MSP430_R3 && get_ad (instr) == 0) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "clr.b" : "clr");
|
||||
remove_first_operand (cmd);
|
||||
} else if (opcode == MSP430_MOV && as != 3 && get_dst (instr) == MSP430_PC
|
||||
&& get_src (instr) != MSP430_SP) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s", "br");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_BIC && as == 2 && get_src (instr) == MSP430_SR) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s", "clrn");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_BIC && as == 2 && get_src (instr) == 3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s", "clrz");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_DADD && as == 0 && get_src (instr) == MSP430_R3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "dadc.b" : "dadc");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_SUB && as == 1 && get_src (instr) == MSP430_R3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "dec.b" : "dec");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_SUB && as == 2 && get_src (instr) == MSP430_R3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "decd.b" : "decd");
|
||||
remove_first_operand (cmd);
|
||||
} else if (opcode == MSP430_BIC && as == 3 && get_src (instr) == MSP430_SR
|
||||
&& get_dst (instr) == MSP430_SR) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s", "dint");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_BIS && as == 3 && get_src (instr) == MSP430_SR
|
||||
&& get_dst (instr) == MSP430_SR) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s", "eint");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_ADD && as == 1 && get_src (instr) == MSP430_R3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "inc.b" : "inc");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_ADD && as == 2 && get_src (instr) == MSP430_R3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "incd.b" : "incd");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_XOR && as == 3 && get_src (instr) != MSP430_R3
|
||||
&& get_src (instr) != MSP430_SR && (dst == 0xFFFF || dst == 0xFF)) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "inv.b" : "inv");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_MOV && as == 0 && get_src (instr) == MSP430_R3
|
||||
&& get_ad (instr) == 0 && get_dst (instr) == 3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "nop");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_MOV && as == 3 && get_src (instr) == MSP430_SP
|
||||
&& get_dst (instr) != MSP430_PC) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "pop.b" : "pop");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_MOV && as == 3 && get_src (instr) == MSP430_SP
|
||||
&& get_dst (instr) == MSP430_PC) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "ret");
|
||||
cmd->type = MSP430_ONEOP;
|
||||
cmd->opcode = MSP430_RETI;
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_ADD && get_src (instr) == get_dst (instr)) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "rla.b" : "rla");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_ADDC && get_src (instr) == get_dst (instr)) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "rlc.b" : "rlc");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_SUBC && as == 0 && get_src (instr) == MSP430_R3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "sbc.b" : "sbc");
|
||||
remove_second_operand (cmd);
|
||||
} else if (opcode == MSP430_BIS && as == 1 && get_dst (instr) == MSP430_R3) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "setc");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_BIS && as == 2 && get_dst (instr) == MSP430_SR) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "setn");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_BIS && as == 2 && get_dst (instr) == MSP430_SR) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "setz");
|
||||
cmd->operands[0] = '\0';
|
||||
} else if (opcode == MSP430_CMP && as == 0 && get_src (instr) == MSP430_SR) {
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
get_bw (instr) ? "tst.b" : "tst");
|
||||
remove_first_operand (cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int decode_addressing_mode (ut16 instr, ut16 dst, ut16 op2, struct msp430_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
ut8 as, ad;
|
||||
char dstbuf[16];
|
||||
|
||||
memset (dstbuf, 0, sizeof (dstbuf));
|
||||
|
||||
as = get_as (instr);
|
||||
ad = get_ad (instr);
|
||||
|
||||
switch (as) {
|
||||
case 0:
|
||||
switch (get_src (instr)) {
|
||||
case MSP430_R3:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#0");
|
||||
break;
|
||||
default:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"r%d", get_src (instr));
|
||||
}
|
||||
ret = 2;
|
||||
break;
|
||||
case 1:
|
||||
ret = 4;
|
||||
switch (get_src (instr)) {
|
||||
case MSP430_PC:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"0x%04x", dst);
|
||||
break;
|
||||
case MSP430_R3:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "%s", "#1");
|
||||
ret = 2;
|
||||
break;
|
||||
case MSP430_SR:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"&0x%04x", dst);
|
||||
break;
|
||||
default:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"0x%x(r%d)", dst, get_src (instr));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (get_src (instr)) {
|
||||
case MSP430_SR:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#4");
|
||||
break;
|
||||
case MSP430_R3:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#2");
|
||||
break;
|
||||
default:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"@r%d", get_src (instr));
|
||||
}
|
||||
|
||||
ret = 2;
|
||||
break;
|
||||
case 3:
|
||||
ret = 2;
|
||||
switch (get_src (instr)) {
|
||||
case MSP430_SR:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#8");
|
||||
break;
|
||||
case MSP430_R3:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#-1");
|
||||
break;
|
||||
case MSP430_PC:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"#0x%04x", dst);
|
||||
ret = 4;
|
||||
break;
|
||||
default:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"@r%d+", get_src (instr));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
switch (ad) {
|
||||
case 0:
|
||||
snprintf (dstbuf, 15, ", r%d", get_dst (instr));
|
||||
break;
|
||||
case 1:
|
||||
switch (get_dst(instr)) {
|
||||
case MSP430_PC:
|
||||
snprintf (dstbuf, 15, ", 0x%04x", dst);
|
||||
if (ret == 2)
|
||||
ret = 4;
|
||||
break;
|
||||
case MSP430_SR:
|
||||
if (as == 1 && get_src (instr) == 2) {
|
||||
snprintf (dstbuf, 15, ", &0x%04x", op2);
|
||||
ret = 6;
|
||||
} else {
|
||||
snprintf (dstbuf, 15, ", &0x%04x", dst);
|
||||
ret = 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (as == 1 && get_src (instr) != 0 && get_src (instr) != 2
|
||||
&& get_src (instr) != 3) {
|
||||
snprintf (dstbuf, 15, ", 0x%x(r%d)", op2, get_dst (instr));
|
||||
ret = 6;
|
||||
} else {
|
||||
snprintf (dstbuf, 15, ", 0x%x(r%d)", dst, get_dst (instr));
|
||||
if (ret == 2)
|
||||
ret = 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
strncat (cmd->operands, dstbuf, MSP430_INSTR_MAXLEN - 1
|
||||
- strlen (cmd->operands));
|
||||
|
||||
decode_emulation (instr, dst, cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int decode_twoop_opcode(ut16 instr, ut16 src, ut16 op2, struct msp430_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
ut8 opcode;
|
||||
|
||||
opcode = get_twoop_opcode (instr);
|
||||
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s", two_op_instrs[opcode]);
|
||||
if (get_bw(instr)) {
|
||||
strncat (cmd->instr, ".b", MSP430_INSTR_MAXLEN - 1 - strlen (cmd->instr));
|
||||
}
|
||||
|
||||
cmd->opcode = get_twoop_opcode (instr);
|
||||
ret = decode_addressing_mode (instr, src, op2, cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ut8 get_jmp_opcode(ut16 instr)
|
||||
{
|
||||
return instr >> 13;
|
||||
}
|
||||
|
||||
static ut8 get_jmp_cond(ut16 instr)
|
||||
{
|
||||
return (instr >> 10 ) & 7;
|
||||
}
|
||||
|
||||
static int decode_jmp (ut16 instr, struct msp430_cmd *cmd)
|
||||
{
|
||||
ut16 addr;
|
||||
if (get_jmp_opcode(instr) != MSP430_JMP_OPC)
|
||||
return -1;
|
||||
|
||||
snprintf(cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
jmp_instrs[get_jmp_cond (instr)]);
|
||||
|
||||
addr = instr & 0x3FF;
|
||||
|
||||
cmd->jmp_addr = addr >= 0x300 ? (st16)((0xFE00 | addr) * 2 + 2) : (addr & 0x1FF) * 2 + 2;
|
||||
snprintf(cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"$%c0x%04x", addr >= 0x300 ? '-' : '+',
|
||||
addr >= 0x300 ? 0x400 - ((addr & 0x1FF) * 2 + 2) : (addr & 0x1FF) * 2 + 2);
|
||||
|
||||
cmd->jmp_cond = get_jmp_cond (instr);
|
||||
cmd->opcode = get_jmp_opcode (instr);
|
||||
cmd->type = MSP430_JUMP;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
static int get_oneop_opcode(ut16 instr)
|
||||
{
|
||||
return (instr >> 7) & 0x7;
|
||||
}
|
||||
|
||||
static int decode_oneop_opcode(ut16 instr, ut16 op, struct msp430_cmd *cmd)
|
||||
{
|
||||
int ret = 2;
|
||||
ut8 ad, opcode;
|
||||
|
||||
if ((instr >> 10) != 4)
|
||||
return -1;
|
||||
|
||||
opcode = get_oneop_opcode (instr);
|
||||
|
||||
ad = get_as (instr);
|
||||
|
||||
snprintf (cmd->instr, MSP430_INSTR_MAXLEN - 1, "%s",
|
||||
one_op_instrs[opcode]);
|
||||
|
||||
cmd->opcode = get_oneop_opcode (instr);
|
||||
|
||||
switch (get_oneop_opcode(instr)) {
|
||||
case MSP430_RCR:
|
||||
case MSP430_SWPB:
|
||||
case MSP430_RRA:
|
||||
case MSP430_SXT:
|
||||
case MSP430_PUSH:
|
||||
case MSP430_CALL:
|
||||
switch (ad) {
|
||||
case 0:
|
||||
switch (get_dst (instr)) {
|
||||
case MSP430_R3:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#0");
|
||||
break;
|
||||
default:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"r%d", get_dst (instr));
|
||||
}
|
||||
ret = 2;
|
||||
break;
|
||||
case 1:
|
||||
switch (get_dst (instr)) {
|
||||
case MSP430_PC:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"0x%04x", op);
|
||||
break;
|
||||
case MSP430_SR:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"&0x%04x", op);
|
||||
break;
|
||||
default:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"0x%x(r%d)", op, get_dst (instr));
|
||||
}
|
||||
|
||||
ret = 4;
|
||||
break;
|
||||
case 2:
|
||||
switch (get_dst (instr)) {
|
||||
case MSP430_SR:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#4");
|
||||
break;
|
||||
case MSP430_R3:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1, "#2");
|
||||
break;
|
||||
default:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"@r%d", get_dst(instr));
|
||||
}
|
||||
|
||||
ret = 2;
|
||||
break;
|
||||
case 3:
|
||||
snprintf (cmd->operands, MSP430_INSTR_MAXLEN - 1,
|
||||
"#0x%04x", op);
|
||||
ret = 4;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case MSP430_RETI:
|
||||
cmd->operands[0] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
cmd->type = MSP430_ONEOP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int msp430_decode_command(const ut8 *in, struct msp430_cmd *cmd)
|
||||
{
|
||||
int ret = -1;
|
||||
ut16 instr;
|
||||
ut16 operand1, operand2;
|
||||
ut8 opcode;
|
||||
|
||||
r_mem_copyendian((ut8*)&instr, in, sizeof (ut16), LIL_ENDIAN);
|
||||
|
||||
opcode = get_twoop_opcode (instr);
|
||||
|
||||
switch (opcode) {
|
||||
case MSP430_MOV:
|
||||
case MSP430_ADD:
|
||||
case MSP430_ADDC:
|
||||
case MSP430_SUBC:
|
||||
case MSP430_SUB:
|
||||
case MSP430_CMP:
|
||||
case MSP430_DADD:
|
||||
case MSP430_BIT:
|
||||
case MSP430_BIC:
|
||||
case MSP430_BIS:
|
||||
case MSP430_XOR:
|
||||
case MSP430_AND:
|
||||
cmd->type = MSP430_TWOOP;
|
||||
r_mem_copyendian((ut8*)&operand1, in + 2, sizeof (ut16), LIL_ENDIAN);
|
||||
r_mem_copyendian((ut8*)&operand2, in + 4, sizeof (ut16), LIL_ENDIAN);
|
||||
ret = decode_twoop_opcode(instr, operand1, operand2, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = decode_jmp (instr, cmd);
|
||||
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
|
||||
r_mem_copyendian((ut8*)&operand1, in + 2, sizeof (ut16), LIL_ENDIAN);
|
||||
ret = decode_oneop_opcode (instr, operand1, cmd);
|
||||
|
||||
return ret;
|
||||
}
|
@ -13,7 +13,7 @@ ALL_TARGETS=
|
||||
# TODO: rename to enabled plugins
|
||||
ARCHS=mips_gnu.mk sparc.mk java.mk bf.mk arm_gnu.mk dalvik.mk x86_as.mk x86_nz.mk
|
||||
ARCHS+=ppc.mk x86_olly.mk x86.mk csr.mk x86_nasm.mk psosvm.mk avr.mk
|
||||
ARCHS+=msil.mk sh.mk arm_winedbg.mk tms320.mk gb.mk snes.mk ebc.mk malbolge.mk ws.mk 6502.mk h8300.mk cr16.mk v850.mk spc700.mk propeller.mk
|
||||
ARCHS+=msil.mk sh.mk arm_winedbg.mk tms320.mk gb.mk snes.mk ebc.mk malbolge.mk ws.mk 6502.mk h8300.mk cr16.mk v850.mk spc700.mk propeller.mk msp430.mk
|
||||
include $(ARCHS)
|
||||
|
||||
all: ${ALL_TARGETS}
|
||||
|
43
libr/asm/p/asm_msp430.c
Normal file
43
libr/asm/p/asm_msp430.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include <msp430_disas.h>
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
struct msp430_cmd cmd;
|
||||
|
||||
ret = msp430_decode_command (buf, &cmd);
|
||||
|
||||
if (ret > 0) {
|
||||
snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s %s", cmd.instr, cmd.operands);
|
||||
}
|
||||
|
||||
op->size = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_msp430 = {
|
||||
.name = "msp430",
|
||||
.license = "LGPL3",
|
||||
.desc = "msp430 disassembly plugin",
|
||||
.arch = "msp430",
|
||||
.bits = 16,
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.disassemble = &disassemble,
|
||||
.modify = NULL,
|
||||
.assemble = NULL,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_propeller,
|
||||
};
|
||||
#endif
|
10
libr/asm/p/msp430.mk
Normal file
10
libr/asm/p/msp430.mk
Normal file
@ -0,0 +1,10 @@
|
||||
OBJ_MSP430=asm_msp430.o
|
||||
OBJ_MSP430+=../arch/msp430/msp430_disas.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_MSP430}
|
||||
TARGET_MSP430=asm_msp430.${EXT_SO}
|
||||
|
||||
ALL_TARGETS+=${TARGET_MSP430}
|
||||
|
||||
${TARGET_MSP430}: ${OBJ_MSP430}
|
||||
${CC} ${LDFLAGS} ${CFLAGS} -I../arch/msp430 -o ${TARGET_MSP430} ${OBJ_MSP430}
|
87
libr/include/msp430_disas.h
Normal file
87
libr/include/msp430_disas.h
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef MSP430_DISAS_H
|
||||
#define MSP430_DISAS_H
|
||||
|
||||
#define MSP430_INSTR_MAXLEN 32
|
||||
|
||||
enum msp430_oneop_opcodes {
|
||||
MSP430_RCR,
|
||||
MSP430_SWPB,
|
||||
MSP430_RRA,
|
||||
MSP430_SXT,
|
||||
MSP430_PUSH,
|
||||
MSP430_CALL,
|
||||
MSP430_RETI,
|
||||
MSP430_UNUSED,
|
||||
};
|
||||
|
||||
enum msp430_jumps {
|
||||
MSP430_JNE,
|
||||
MSP430_JEQ,
|
||||
MSP430_JNC,
|
||||
MSP430_JC,
|
||||
MSP430_JN,
|
||||
MSP430_JGE,
|
||||
MSP430_JL,
|
||||
MSP430_JMP,
|
||||
};
|
||||
|
||||
enum msp430_twoop_opcodes {
|
||||
MSP430_JMP_OPC = 0x1,
|
||||
MSP430_MOV = 0x4,
|
||||
MSP430_ADD,
|
||||
MSP430_ADDC,
|
||||
MSP430_SUBC,
|
||||
MSP430_SUB,
|
||||
MSP430_CMP,
|
||||
MSP430_DADD,
|
||||
MSP430_BIT,
|
||||
MSP430_BIC,
|
||||
MSP430_BIS,
|
||||
MSP430_XOR,
|
||||
MSP430_AND,
|
||||
};
|
||||
|
||||
enum msp430_addr_modes {
|
||||
MSP430_DIRECT,
|
||||
MSP430_INDEXED,
|
||||
MSP430_INDIRECT,
|
||||
MSP430_INDIRECT_INC,
|
||||
};
|
||||
|
||||
enum msp430_cmd_type {
|
||||
MSP430_ONEOP,
|
||||
MSP430_TWOOP,
|
||||
MSP430_JUMP,
|
||||
};
|
||||
|
||||
enum msp430_registers {
|
||||
MSP430_PC,
|
||||
MSP430_SP,
|
||||
MSP430_SR,
|
||||
MSP430_R3,
|
||||
MSP430_R4,
|
||||
MSP430_R5,
|
||||
MSP430_R6,
|
||||
MSP430_R7,
|
||||
MSP430_R8,
|
||||
MSP430_R9,
|
||||
MSP430_R10,
|
||||
MSP430_R11,
|
||||
MSP430_R12,
|
||||
MSP430_R13,
|
||||
MSP430_R14,
|
||||
MSP430_R15,
|
||||
};
|
||||
|
||||
struct msp430_cmd {
|
||||
ut8 type;
|
||||
ut16 opcode;
|
||||
st16 jmp_addr;
|
||||
ut16 call_addr;
|
||||
ut8 jmp_cond;
|
||||
char instr[MSP430_INSTR_MAXLEN];
|
||||
char operands[MSP430_INSTR_MAXLEN];
|
||||
};
|
||||
|
||||
int msp430_decode_command(const ut8 *instr, struct msp430_cmd *cmd);
|
||||
#endif /* MSP430_DISAS_H */
|
@ -1254,6 +1254,7 @@ extern RAnalPlugin r_anal_plugin_sysz;
|
||||
extern RAnalPlugin r_anal_plugin_sparc_cs;
|
||||
extern RAnalPlugin r_anal_plugin_xcore_cs;
|
||||
extern RAnalPlugin r_anal_plugin_propeller;
|
||||
extern RAnalPlugin r_anal_plugin_msp430;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -204,6 +204,7 @@ extern RAsmPlugin r_asm_plugin_sparc_cs;
|
||||
extern RAsmPlugin r_asm_plugin_xcore_cs;
|
||||
extern RAsmPlugin r_asm_plugin_spc700;
|
||||
extern RAsmPlugin r_asm_plugin_propeller;
|
||||
extern RAsmPlugin r_asm_plugin_msp430;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -321,6 +321,7 @@ enum {
|
||||
R_SYS_ARCH_SYSZ = 0x1000000,
|
||||
R_SYS_ARCH_XCORE = 0x2000000,
|
||||
R_SYS_ARCH_PROPELLER = 0x4000000,
|
||||
R_SYS_ARCH_MSP430 = 0x8000000,
|
||||
};
|
||||
|
||||
/* os */
|
||||
|
@ -29,6 +29,7 @@ asm.dcpu16
|
||||
asm.m68k
|
||||
asm.mips_gnu
|
||||
asm.mips_cs
|
||||
asm.msp430
|
||||
asm.rar
|
||||
asm.x86
|
||||
asm.x86_olly
|
||||
@ -80,6 +81,7 @@ anal.h8300
|
||||
anal.cr16
|
||||
anal.v850
|
||||
anal.xcore_cs
|
||||
anal.msp430
|
||||
bin.any
|
||||
bin.bios
|
||||
bin.bf
|
||||
|
Loading…
Reference in New Issue
Block a user