From 7b033959bf69492238044850f203c6621a36eada Mon Sep 17 00:00:00 2001 From: billow Date: Tue, 16 Jan 2024 08:45:43 +0800 Subject: [PATCH] v850 refactor v850_disas.c --- librz/analysis/arch/v850/v850_esil.inc | 70 +++++----- librz/analysis/arch/v850/v850_il.c | 170 ++++++++++++----------- librz/analysis/arch/v850/v850_il.h | 1 + librz/analysis/p/analysis_v850.c | 32 ++--- librz/asm/arch/v850/v850_disas.c | 178 ++++++++++++++++--------- librz/asm/arch/v850/v850_disas.h | 46 +++++-- 6 files changed, 277 insertions(+), 220 deletions(-) diff --git a/librz/analysis/arch/v850/v850_esil.inc b/librz/analysis/arch/v850/v850_esil.inc index 23d90075ecd..42622700dcf 100644 --- a/librz/analysis/arch/v850/v850_esil.inc +++ b/librz/analysis/arch/v850/v850_esil.inc @@ -32,13 +32,13 @@ static void clear_flags(RzStrBuf *out, int flags) { } } -static void v850_esil(RzStrBuf *out, ut8 opcode, ut16 word1, ut16 word2) { +static void v850_esil(RzStrBuf *out, ut8 opcode, ut16 word1, ut16 word2, struct v850_cmd *x) { const char *reg1 = NULL; const char *reg2 = NULL; ut32 bitmask = 0; ut16 destaddr = 0; st16 destaddrs = 0; - switch (opcode) { + switch (x->opcode) { case V850_MOV_IMM5: case V850_MOV: // 2 formats @@ -180,9 +180,6 @@ static void v850_esil(RzStrBuf *out, ut8 opcode, ut16 word1, ut16 word2) { clear_flags(out, V850_FLAG_OV); break; case V850_BCOND: - case V850_BCOND2: - case V850_BCOND3: - case V850_BCOND4: destaddr = ((((word1 >> 4) & 0x7) | ((word1 >> 11) << 3)) << 1); @@ -240,41 +237,34 @@ static void v850_esil(RzStrBuf *out, ut8 opcode, ut16 word1, ut16 word2) { } rz_strbuf_appendf(out, ",?{,$$,%d,+,pc,=,}", destaddrs); break; - case V850_BIT_MANIP: { - ut8 bitop = word1 >> 14; - switch (bitop) { - case V850_BIT_CLR1: - bitmask = (1 << F8_BIT(word1)); - rz_strbuf_appendf(out, "%hu,%s,+,[1],%u,&,%hu,%s,+,=[1]", word2, F8_RN1(word1), bitmask, word2, F8_RN1(word1)); - // TODO: Read the value of the memory byte and set zero flag accordingly! - break; - case V850_BIT_NOT1: - bitmask = (1 << F8_BIT(word1)); - rz_strbuf_appendf(out, "%hu,%s,+,[1],%u,^,%hu,%s,+,=[1]", word2, F8_RN1(word1), bitmask, word2, F8_RN1(word1)); - // TODO: Read the value of the memory byte and set zero flag accordingly! - break; - } - } break; - case V850_EXT1: - switch (get_subopcode(word1 | (ut32)word2 << 16)) { - case V850_EXT_SHL: - rz_strbuf_appendf(out, "%s,%s,<<=", F9_RN1(word1), F9_RN2(word1)); - update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z); - clear_flags(out, V850_FLAG_OV); - break; - case V850_EXT_SHR: - rz_strbuf_appendf(out, "%s,%s,>>=", F9_RN1(word1), F9_RN2(word1)); - update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z); - clear_flags(out, V850_FLAG_OV); - break; - case V850_EXT_SAR: - reg1 = F9_RN1(word1); - reg2 = F9_RN2(word1); - rz_strbuf_appendf(out, "31,%s,>>,?{,%s,32,-,%s,1,<<,--,<<,}{,0,},%s,%s,>>,|,%s,=", reg2, reg1, reg1, reg1, reg2, reg2); - update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z); - clear_flags(out, V850_FLAG_OV); - break; - } + case V850_CLR1: + bitmask = (1 << F8_BIT(word1)); + rz_strbuf_appendf(out, "%hu,%s,+,[1],%u,&,%hu,%s,+,=[1]", word2, F8_RN1(word1), bitmask, word2, F8_RN1(word1)); + // TODO: Read the value of the memory byte and set zero flag accordingly! + break; + case V850_NOT1: + bitmask = (1 << F8_BIT(word1)); + rz_strbuf_appendf(out, "%hu,%s,+,[1],%u,^,%hu,%s,+,=[1]", word2, F8_RN1(word1), bitmask, word2, F8_RN1(word1)); + // TODO: Read the value of the memory byte and set zero flag accordingly! + break; + + case V850_SHL: + rz_strbuf_appendf(out, "%s,%s,<<=", F9_RN1(word1), F9_RN2(word1)); + update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z); + clear_flags(out, V850_FLAG_OV); + break; + case V850_SHR: + rz_strbuf_appendf(out, "%s,%s,>>=", F9_RN1(word1), F9_RN2(word1)); + update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z); + clear_flags(out, V850_FLAG_OV); + break; + case V850_SAR: + reg1 = F9_RN1(word1); + reg2 = F9_RN2(word1); + rz_strbuf_appendf(out, "31,%s,>>,?{,%s,32,-,%s,1,<<,--,<<,}{,0,},%s,%s,>>,|,%s,=", reg2, reg1, reg1, reg1, reg2, reg2); + update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z); + clear_flags(out, V850_FLAG_OV); break; + default: break; } } \ No newline at end of file diff --git a/librz/analysis/arch/v850/v850_il.c b/librz/analysis/arch/v850/v850_il.c index b48d571879a..7e2a9e08680 100644 --- a/librz/analysis/arch/v850/v850_il.c +++ b/librz/analysis/arch/v850/v850_il.c @@ -88,26 +88,67 @@ static const char *GR[] = { "ep", // EP "lp", // LP /*PC*/ - NULL }; -typedef struct { - const char *p; - const char *x; - unsigned i; - unsigned b; -} V850_FLG; - static const char *SR[] = { "EIPC", "EIPSW", "FEPC", "FEPSW", "ECR", - "PSW", - NULL + "PSW", // 5 + "RES6", + "RES7", + "RES8", + "RES9", + "RES10", + "RES11", + "RES12", + "RES6", + "RES13", + "RES14", + "RES15", + "RES16", + "RES17", + "RES18", + "RES19", + "RES20", + "RES21", + "RES22", + "RES23", + "RES24", + "RES25", + "RES26", + "RES27", + "RES28", + "RES29", + "RES30", + "RES31", }; +static const char *GR_get(ut8 i) { + if (i >= RZ_ARRAY_SIZE(GR)) { + rz_warn_if_reached(); + return NULL; + } + return GR[i]; +} + +static const char *SR_get(ut8 i) { + if (i >= RZ_ARRAY_SIZE(SR)) { + rz_warn_if_reached(); + return NULL; + } + return SR[i]; +} + +typedef struct { + const char *p; + const char *x; + unsigned i; + unsigned b; +} V850_FLG; + static const V850_FLG flags[] = { { "PSW", "RFU", 8, 24 }, { "PSW", "NP", 7, 1 }, @@ -196,8 +237,8 @@ static inline int32_t sext32(uint32_t X, unsigned B) { #define R1_ get_reg1(ctx->w1) #define R2_ get_reg2(ctx->w1) -#define R1 (GR[R1_]) -#define R2 (GR[R2_]) +#define R1 (GR_get(R1_)) +#define R2 (GR_get(R2_)) #define R1V VARG(R1) #define R2V VARG(R2) #define R1F FLOATV32(VARG(R1)) @@ -292,7 +333,7 @@ static RzILOpPure *condition_table(ut8 x) { } static RzAnalysisLiftedILOp flags_update(const V850AnalysisContext *ctx, RzILOpPure *a, RzILOpPure *b) { - switch (OPC) { + switch (ctx->x->opcode) { case V850_ADD: case V850_ADD_IMM5: case V850_ADDI: @@ -315,33 +356,20 @@ static RzAnalysisLiftedILOp flags_update(const V850AnalysisContext *ctx, RzILOpP "OV", IS_ZERO(LH(R1V)), "S", SLT(VARL("result"), S32(0)), "Z", IS_ZERO(VARL("result"))); - case V850_SHR_IMM5: - case V850_SAR_IMM5: return SETGbs("PSW", 4, - "CY", AND(NON_ZERO(DUP(b)), NON_ZERO(LOGAND(DUP(a), SUB(SHIFTL0(U32(1), DUP(b)), U32(1))))), + case V850_SHL_IMM5: + case V850_SHL: return SETGbs("PSW", 4, + "CY", AND(NON_ZERO(DUP(b)), NON_ZERO(shr0(DUP(a), SUB(U32(32), DUP(b))))), "OV", IL_FALSE, "S", SLT(VARL("result"), S32(0)), "Z", IS_ZERO(VARL("result"))); - case V850_SHL_IMM5: return SETGbs("PSW", 4, - "CY", AND(NON_ZERO(DUP(b)), NON_ZERO(shr0(DUP(a), SUB(U32(32), DUP(b))))), + case V850_SHR_IMM5: + case V850_SAR_IMM5: + case V850_SHR: + case V850_SAR: return SETGbs("PSW", 4, + "CY", AND(NON_ZERO(DUP(b)), NON_ZERO(LOGAND(DUP(a), SUB(SHIFTL0(U32(1), DUP(b)), U32(1))))), "OV", IL_FALSE, "S", SLT(VARL("result"), S32(0)), "Z", IS_ZERO(VARL("result"))); - case V850_EXT1: - switch (EXT_SUB) { - case V850_EXT_SHL: return SETGbs("PSW", 4, - "CY", AND(NON_ZERO(DUP(b)), NON_ZERO(shr0(DUP(a), SUB(U32(32), DUP(b))))), - "OV", IL_FALSE, - "S", SLT(VARL("result"), S32(0)), - "Z", IS_ZERO(VARL("result"))); - case V850_EXT_SHR: - case V850_EXT_SAR: return SETGbs("PSW", 4, - "CY", AND(NON_ZERO(DUP(b)), NON_ZERO(LOGAND(DUP(a), SUB(SHIFTL0(U32(1), DUP(b)), U32(1))))), - "OV", IL_FALSE, - "S", SLT(VARL("result"), S32(0)), - "Z", IS_ZERO(VARL("result"))); - default: break; - } - break; case V850_SATADD: case V850_SATADD_IMM5: case V850_SATSUB: @@ -476,7 +504,7 @@ static RzAnalysisLiftedILOp lift_tst1(const V850AnalysisContext *ctx) { } RzAnalysisLiftedILOp v850_il_op(const V850AnalysisContext *ctx) { - switch (OPC) { + switch (ctx->x->opcode) { case V850_MOV_IMM5: return SETG(R2, SEXT5); case V850_MOV: return SETG(R2, R1V); case V850_MOVEA: return SETG(R2, ADD(R1V, SEXT16)); @@ -488,21 +516,11 @@ RzAnalysisLiftedILOp v850_il_op(const V850AnalysisContext *ctx) { case V850_SSTH: return lift_st(ctx, ADD(VARG("ep"), U32(LD_ST_DISP_ << 1)), 16); case V850_SSTW: return lift_st(ctx, ADD(VARG("ep"), U32((LD_ST_DISP_ & ~1) << 1)), 32); case V850_STB: return lift_st(ctx, ADD(R1V, SEXT16), 8); - case V850_STHW: { - if (LD_ST32_SUB == 0) { - return lift_st(ctx, ADD(R1V, S32(I16 & ~1)), 16); - } else { - return lift_st(ctx, ADD(R1V, S32(I16 & ~1)), 32); - } - } + case V850_STH: return lift_st(ctx, ADD(R1V, S32(I16 & ~1)), 16); + case V850_STW: return lift_st(ctx, ADD(R1V, S32(I16 & ~1)), 32); case V850_LDB: return lift_ld(ctx, ADD(R1V, SEXT16), 8); - case V850_LDHW: { - if (LD_ST32_SUB == 0) { - return lift_ld(ctx, ADD(R1V, S32(I16 & ~1)), 16); - } else { - return lift_ld(ctx, ADD(R1V, S32(I16 & ~1)), 32); - } - } + case V850_LDH: return lift_ld(ctx, ADD(R1V, S32(I16 & ~1)), 16); + case V850_LDW: return lift_ld(ctx, ADD(R1V, S32(I16 & ~1)), 32); case V850_NOT: return lift_op1(ctx, R1V, rz_il_op_new_log_not); case V850_DIVH: return lift_op2(ctx, R2V, LH(R1V), rz_il_op_new_div); case V850_JMP: return JMP(R1V); @@ -533,44 +551,24 @@ RzAnalysisLiftedILOp v850_il_op(const V850AnalysisContext *ctx) { case V850_SHR_IMM5: return lift_op2(ctx, R2V, ZEXT5, shr0); case V850_SAR_IMM5: return lift_op2(ctx, R2V, ZEXT5, rz_il_op_new_shiftr_arith); case V850_SHL_IMM5: return lift_op2(ctx, R2V, ZEXT5, shl0); - case V850_BCOND: - case V850_BCOND2: - case V850_BCOND3: - case V850_BCOND4: return lift_bcond(ctx, condition_table(BCOND_COND)); - case V850_BIT_MANIP: { - switch (BIT_SUB) { - case V850_BIT_CLR1: return lift_bit(ctx, ADD(R1V, SEXT16), 0); - case V850_BIT_SET1: return lift_bit(ctx, ADD(R1V, SEXT16), 1); - case V850_BIT_NOT1: return lift_bit(ctx, ADD(R1V, SEXT16), PSW_Z); - case V850_BIT_TST1: return lift_tst1(ctx); - default: break; - } - break; - } - case V850_EXT1: - switch (EXT_SUB) { - case V850_EXT_SHL: return lift_op2(ctx, R2V, R1V, shl0); - case V850_EXT_SHR: return lift_op2(ctx, R2V, R1V, shr0); - case V850_EXT_SAR: return lift_op2(ctx, R2V, R1V, rz_il_op_new_shiftr_arith); - case V850_EXT_HALT: return NOP(); - case V850_EXT_RETI: return lift_reti(ctx); - case V850_EXT_SETF: return SETG(R2, ITE(condition_table(EXT_COND), U32((1)), U32(0))); - case V850_EXT_STSR: return SETG(R2, VARG(SR[regID])); - case V850_EXT_LDSR: return SETG(SR[regID], R2V); - case V850_EXT_TRAP: return lift_trap(ctx); - case V850_EXT_EXT2: { - switch (EXT_SUB2) { - case V850_EXT_DI: return SETGb("PSW", "ID", IL_TRUE); - case V850_EXT_EI: return SETGb("PSW", "ID", IL_FALSE); - } - } - default: break; - } - break; + case V850_BCOND: return lift_bcond(ctx, condition_table(BCOND_COND)); + case V850_CLR1: return lift_bit(ctx, ADD(R1V, SEXT16), 0); + case V850_SET1: return lift_bit(ctx, ADD(R1V, SEXT16), 1); + case V850_NOT1: return lift_bit(ctx, ADD(R1V, SEXT16), PSW_Z); + case V850_TST1: return lift_tst1(ctx); + case V850_SHL: return lift_op2(ctx, R2V, R1V, shl0); + case V850_SHR: return lift_op2(ctx, R2V, R1V, shr0); + case V850_SAR: return lift_op2(ctx, R2V, R1V, rz_il_op_new_shiftr_arith); + case V850_HALT: return NOP(); + case V850_RETI: return lift_reti(ctx); + case V850_SETF: return SETG(R2, ITE(condition_table(EXT_COND), U32((1)), U32(0))); + case V850_STSR: return SETG(R2, VARG(SR_get(regID))); + case V850_LDSR: return SETG(SR_get(ctx->w1 >> 11), VARG(GR_get(I5))); + case V850_TRAP: return lift_trap(ctx); + case V850_DI: return SETGb("PSW", "ID", IL_TRUE); + case V850_EI: return SETGb("PSW", "ID", IL_FALSE); + case V850_NOP: return NOP(); default: - if (ctx->w1 == 0x0000) { - return NOP(); - } break; } diff --git a/librz/analysis/arch/v850/v850_il.h b/librz/analysis/arch/v850/v850_il.h index 5cb57e771d9..2dd500de3ea 100644 --- a/librz/analysis/arch/v850/v850_il.h +++ b/librz/analysis/arch/v850/v850_il.h @@ -38,6 +38,7 @@ typedef struct { ut16 w1; ut16 w2; ut32 pc; + struct v850_cmd *x; } V850AnalysisContext; RzAnalysisILConfig *v850_il_config(RzAnalysis *a); diff --git a/librz/analysis/p/analysis_v850.c b/librz/analysis/p/analysis_v850.c index 5d4628eeeb9..41e83166f20 100644 --- a/librz/analysis/p/analysis_v850.c +++ b/librz/analysis/p/analysis_v850.c @@ -164,9 +164,8 @@ static int v850_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 if (ret == 4) { word2 = rz_read_le16(buf + 2); } - opcode = get_opcode(word1); - switch (opcode) { + switch (cmd.opcode) { case V850_MOV_IMM5: case V850_MOV: case V850_MOVEA: @@ -270,9 +269,6 @@ static int v850_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 op->type = RZ_ANALYSIS_OP_TYPE_SHL; break; case V850_BCOND: - case V850_BCOND2: - case V850_BCOND3: - case V850_BCOND4: destaddr = ((((word1 >> 4) & 0x7) | ((word1 >> 11) << 3)) << 1); @@ -285,24 +281,21 @@ static int v850_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 op->fail = addr + 2; op->type = RZ_ANALYSIS_OP_TYPE_CJMP; break; - case V850_BIT_MANIP: break; - case V850_EXT1: - switch (get_subopcode(word1 | (ut32)word2 << 16)) { - case V850_EXT_SHL: - op->type = RZ_ANALYSIS_OP_TYPE_SHL; - break; - case V850_EXT_SHR: - op->type = RZ_ANALYSIS_OP_TYPE_SHR; - break; - case V850_EXT_SAR: - op->type = RZ_ANALYSIS_OP_TYPE_SAR; - break; - } + + case V850_SHL: + op->type = RZ_ANALYSIS_OP_TYPE_SHL; + break; + case V850_SHR: + op->type = RZ_ANALYSIS_OP_TYPE_SHR; + break; + case V850_SAR: + op->type = RZ_ANALYSIS_OP_TYPE_SAR; break; + default: break; } if (mask & RZ_ANALYSIS_OP_MASK_ESIL) { - v850_esil(&op->esil, opcode, word1, word2); + v850_esil(&op->esil, opcode, word1, word2, &cmd); } if (mask & RZ_ANALYSIS_OP_MASK_DISASM) { @@ -315,6 +308,7 @@ static int v850_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 ctx.w1 = word1; ctx.w2 = word2; ctx.pc = addr; + ctx.x = &cmd; op->il_op = v850_il_op(&ctx); } diff --git a/librz/asm/arch/v850/v850_disas.c b/librz/asm/arch/v850/v850_disas.c index 78b0356593d..831cd0052b2 100644 --- a/librz/asm/arch/v850/v850_disas.c +++ b/librz/asm/arch/v850/v850_disas.c @@ -47,12 +47,27 @@ static const char *instrs[] = { [V850_XORI] = "xori", [V850_ANDI] = "andi", [V850_MULHI] = "mulhi", - [V850_LDB] = "ld", - [V850_LDHW] = "ld", - [V850_STB] = "st", - [V850_STHW] = "st", - [V850_BIT_MANIP] = "", - [V850_EXT1] = "", + [V850_LDB] = "ld.b", + [V850_LDH] = "ld.h", + [V850_LDW] = "ld.w", + [V850_STB] = "st.b", + [V850_STH] = "st.h", + [V850_STW] = "st.w", + [V850_SET1] = "set1", + [V850_NOT1] = "not1", + [V850_CLR1] = "clr1", + [V850_TST1] = "tst1", + [V850_SETF] = "setf", + [V850_LDSR] = "ldsr", + [V850_STSR] = "stsr", + [V850_SHR] = "shr", + [V850_SAR] = "sar", + [V850_SHL] = "shl", + [V850_TRAP] = "trap", + [V850_HALT] = "halt", + [V850_RETI] = "reti", + [V850_DI] = "di", + [V850_EI] = "ei", }; static const char *bit_instrs[] = { @@ -150,19 +165,13 @@ static int decode_imm_reg(const ut16 instr, struct v850_cmd *cmd) { } static int decode_bcond(const ut16 instr, int len, struct v850_cmd *cmd) { -#if 0 - ut16 disp = ((instr >> 4) & 0x7) | (instr >> 11); - disp <<= 1; - snprintf (cmd->instr, V850_INSTR_MAXLEN - 1, "b%s", conds[instr & 0xF]); - snprintf (cmd->operands, V850_INSTR_MAXLEN - 1, "0x%x", disp); -#else ut64 delta = ((((instr >> 4) & 0x7) | ((instr >> 11) << 3)) << 1); if (delta & 0x100) { delta |= 0xFE00; } + cmd->opcode = V850_BCOND; snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "b%s", conds[instr & 0xF]); snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "0x%08" PFMT64x, cmd->addr + delta); -#endif return 2; } @@ -178,14 +187,16 @@ static int decode_jump(const ut8 *instr, int len, struct v850_cmd *cmd) { ut8 reg = get_reg2(word1); if (reg > 0) { + cmd->opcode = V850_JARL; ut16 word2 = rz_read_at_le16(instr, 2); ut32 disp = (word2 << 6) | get_reg1(word1); snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s", "jarl"); snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "0x%08x, r%d", disp << 1, reg); } else { + cmd->opcode = V850_JR; ut8 reg1 = get_reg1(word1); - snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s", "jmp"); + snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s", "jr"); snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "r%d", reg1); } @@ -212,31 +223,48 @@ static int decode_load_store(const ut8 *instr, int len, struct v850_cmd *cmd) { ut16 word1 = rz_read_le16(instr); ut16 word2 = rz_read_at_le16(instr, 2); - switch (get_opcode(word1)) { + ut8 opc = get_opcode(word1); + ut8 opc1 = word2 & 0x1; + V850_Opcode opcode = 0; + switch (opc) { case V850_STB: - snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s.b", instrs[get_opcode(word1)]); + opcode = V850_STB; snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "r%d, 0x%x[r%d]", get_reg2(word1), word2, get_reg1(word1)); break; case V850_LDB: - snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s.b", instrs[get_opcode(word1)]); + opcode = V850_LDB; snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "0x%x[r%d], r%d", get_reg1(word1), word2, get_reg2(word1)); + break; - case V850_LDHW: - snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s.%c", - instrs[get_opcode(word1)], word2 & 1 ? 'w' : 'h'); - snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "0x%x[r%d], r%d", - word2 & 0xFFFE, get_reg1(word1), get_reg2(word1)); - break; - case V850_STHW: - snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s.%c", - instrs[get_opcode(word1)], word2 & 1 ? 'w' : 'h'); - snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "r%d, 0x%x[r%d]", - get_reg2(word1), word2 & 0xFFFE, get_reg1(word1)); - break; + default: { + // LDHW + if (opc == 0b111001) { + if (opc1) { + opcode = V850_LDW; + } else { + opcode = V850_LDH; + } + snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "0x%x[r%d], r%d", + word2 & 0xFFFE, get_reg1(word1), get_reg2(word1)); + break; + } + // STHW + if (opc == 0b111011) { + if (opc1) { + opcode = V850_STW; + } else { + opcode = V850_STH; + } + snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "r%d, 0x%x[r%d]", + get_reg2(word1), word2 & 0xFFFE, get_reg1(word1)); + break; + } } - + } + cmd->opcode = opcode; + snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s", instrs[opcode]); return 4; } @@ -251,6 +279,8 @@ static int decode_bit_op(const ut8 *instr, int len, struct v850_cmd *cmd) { ut8 reg1 = get_reg1(word1); snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "%u, 0x%x[r%d]", (word1 >> 11) & 0x7, word2, reg1); + + cmd->opcode = (word1 >> 14) + V850_SET1; return 4; } @@ -262,40 +292,53 @@ static int decode_extended(const ut8 *instr, int len, struct v850_cmd *cmd) { ut16 word1 = rz_read_le16(instr); ut16 word2 = rz_read_at_le16(instr, 2); + ut8 subopc = (word2 >> 5) & 0x3f; + ut8 subopc2 = word1 >> 13; + if (subopc == 0xb) { + if (subopc2) { + cmd->opcode = V850_EI; + } else { + cmd->opcode = V850_DI; + } + } else { + cmd->opcode = V850_SETF + subopc; + } + snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s", - ext_instrs1[get_subopcode(word1)]); + ext_instrs1[subopc]); - switch (get_subopcode(word1)) { - case V850_EXT_SETF: + switch (cmd->opcode) { + case V850_SETF: snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "%s, r%d", conds[word1 & 0xF], get_reg2(word1)); break; - case V850_EXT_LDSR: + case V850_LDSR: snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "r%d, r%d", get_reg2(word1), get_reg1(word1)); break; - case V850_EXT_STSR: + case V850_STSR: snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "r%d, r%d", get_reg1(word1), get_reg2(word1)); break; - case V850_EXT_SHR: - case V850_EXT_SAR: - case V850_EXT_SHL: + case V850_SHR: + case V850_SAR: + case V850_SHL: snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "r%d, r%d", get_reg1(word1), get_reg2(word2)); break; - case V850_EXT_TRAP: + case V850_TRAP: snprintf(cmd->operands, V850_INSTR_MAXLEN - 1, "0x%x", get_reg1(word1)); break; - case V850_EXT_HALT: - case V850_EXT_RETI: + case V850_HALT: + case V850_RETI: cmd->operands[0] = '\0'; break; - case V850_EXT_EXT2: + case V850_DI: + case V850_EI: // can be only 0 or 1 snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s", - ext_instrs2[(word2 >> 13) & 1]); + ext_instrs2[subopc2]); break; default: return -1; @@ -311,8 +354,8 @@ int v850_decode_command(const ut8 *instr, int len, struct v850_cmd *cmd) { return -1; } ut16 in = rz_read_le16(instr); - - switch (get_opcode(in)) { + ut8 opc = get_opcode(in); + switch (opc) { case V850_MOV: case V850_NOT: case V850_DIVH: @@ -351,25 +394,38 @@ int v850_decode_command(const ut8 *instr, int len, struct v850_cmd *cmd) { case V850_MULHI: ret = decode_3operands(instr, len, cmd); break; - case V850_STB: - case V850_LDB: - case V850_LDHW: - case V850_STHW: - ret = decode_load_store(instr, len, cmd); - break; - case V850_BIT_MANIP: - ret = decode_bit_op(instr, len, cmd); - break; - case V850_EXT1: - ret = decode_extended(instr, len, cmd); - break; - default: + default: { + if (opc == 0b111010 || + opc == 0b111011 || + opc == 0b111000 || + opc == 0b111001) { + return decode_load_store(instr, len, cmd); + } + + if (opc == 0x3e) { + return decode_bit_op(instr, len, cmd); + } + + if (opc == 0b111111 || + opc == 0b111110) { + return decode_extended(instr, len, cmd); + } if ((get_opcode(in) >> 2) == 0xB) { - ret = decode_bcond(in, len, cmd); - } else { - ret = decode_jump(instr, len, cmd); + return decode_bcond(in, len, cmd); + } + + ut8 opcj = (in >> 6) & 0x1f; + if (opcj == 0b11110) { + return decode_jump(instr, len, cmd); + } + + if (in == 0) { + cmd->opcode = V850_NOP; + snprintf(cmd->instr, V850_INSTR_MAXLEN - 1, "%s", "nop"); } } + } + cmd->opcode = opc; return ret; } diff --git a/librz/asm/arch/v850/v850_disas.h b/librz/asm/arch/v850/v850_disas.h index ea51705ac71..b46d35a4e60 100644 --- a/librz/asm/arch/v850/v850_disas.h +++ b/librz/asm/arch/v850/v850_disas.h @@ -6,11 +6,11 @@ #define V850_INSTR_MAXLEN 24 -#define SIGN_EXT_T5(imm) (((imm)&0x10) ? (imm) | 0xE0 : (imm)) -#define SIGN_EXT_T9(imm) (((imm)&0x100) ? (imm) | 0xFFFFFE00 : (imm)) -#define SIGN_EXT_T26(imm) (((imm)&0x2000000) ? (imm) | 0xFC000000 : (imm)) +#define SIGN_EXT_T5(imm) (((imm) & 0x10) ? (imm) | 0xE0 : (imm)) +#define SIGN_EXT_T9(imm) (((imm) & 0x100) ? (imm) | 0xFFFFFE00 : (imm)) +#define SIGN_EXT_T26(imm) (((imm) & 0x2000000) ? (imm) | 0xFC000000 : (imm)) -enum v850_cmd_opcodes { +typedef enum v850_cmd_opcodes { V850_MOV = 0x0, V850_NOT = 0x1, V850_DIVH = 0x2, @@ -41,10 +41,7 @@ enum v850_cmd_opcodes { V850_SSTH = 0x24, V850_SLDW = 0x28, V850_SSTW = 0x29, - V850_BCOND = 0x2C, - V850_BCOND2 = 0x2D, - V850_BCOND3 = 0x2E, - V850_BCOND4 = 0x2F, + V850_BCOND, V850_ADDI = 0x30, V850_MOVEA = 0x31, V850_MOVHI = 0x32, @@ -54,14 +51,34 @@ enum v850_cmd_opcodes { V850_ANDI = 0x36, V850_MULHI = 0x37, V850_LDB = 0x38, - V850_LDHW = 0x39, - V850_STB = 0x3A, - V850_STHW = 0x3B, - V850_BIT_MANIP = 0x3E, - V850_EXT1 = 0x3F, + V850_LDH, + V850_LDW, + V850_STB, + V850_STH, + V850_STW, + + V850_SET1, + V850_NOT1, + V850_CLR1, + V850_TST1, + + V850_SETF, + V850_LDSR, + V850_STSR, + V850_SHR, + V850_SAR, + V850_SHL, + V850_TRAP, + V850_HALT, + V850_RETI, + + V850_DI, + V850_EI, + V850_JARL, V850_JR, -}; + V850_NOP, +} V850_Opcode; enum v850_conds { V850_COND_V = 0x0, // Overflow @@ -170,6 +187,7 @@ enum v850_flags { }; struct v850_cmd { + V850_Opcode opcode; ut64 addr; unsigned type; char instr[V850_INSTR_MAXLEN];