diff --git a/librz/asm/arch/v850/v850_disas.c b/librz/asm/arch/v850/v850_disas.c index b7daa24396d..b342e0f2c06 100644 --- a/librz/asm/arch/v850/v850_disas.c +++ b/librz/asm/arch/v850/v850_disas.c @@ -98,7 +98,7 @@ static const char *instrs[] = { [V850_JR] = "jr", [V850_CALLT] = "callt", [V850_CAXI] = "caxi", - [V850_CLI] = "cli", + [V850_CLL] = "cll", [V850_CTRET] = "ctret", [V850_DI] = "di", [V850_DISPOSE] = "dispose", @@ -118,7 +118,7 @@ static const char *instrs[] = { [V850_STSR] = "stsr", [V850_STCW] = "stcw", [V850_SWITCH] = "switch", - [V850_STNCE] = "stnce", + [V850_SYNCE] = "synce", [V850_SYNCI] = "synci", [V850_SYNCM] = "syncm", [V850_SYNCP] = "syncp", @@ -148,56 +148,138 @@ static const char *conds[] = { #define INSTR(...) snprintf(inst->instr, V850_INSTR_MAXLEN - 1, __VA_ARGS__); #define OPERANDS(...) snprintf(inst->operands, V850_INSTR_MAXLEN - 1, __VA_ARGS__); -static bool decode_formatI(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatI(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->reg2 = get_reg2(inst); inst->reg1 = get_reg1(inst); - inst->byte_size = 2; + switch (inst->opcode) { + case V850_ADD: + case V850_AND: + case V850_CMP: + case V850_DIVH: + case V850_FETRAP: + case V850_JMP: + case V850_MOV: + case V850_MULH: + case V850_NOP: + case V850_NOT: + case V850_OR: + case V850_RIE: + case V850_SATADD: + case V850_SATSUB: + case V850_SATSUBR: + case V850_SUB: + case V850_SUBR: + case V850_SWITCH: + case V850_SXB: + case V850_SXH: + case V850_SYNCE: + case V850_SYNCI: + case V850_SYNCM: + case V850_SYNCP: + case V850_TST: + case V850_XOR: + case V850_ZXB: + case V850_ZXH: inst->id = inst->opcode; break; + default: return false; + } + const char *instr = instrs[inst->id]; const char *r2 = GR_get(inst->reg2); const char *r1 = GR_get(inst->reg1); - if (!(r2 && r1)) { + if (!(r2 && r1 && instr)) { return false; } - INSTR("%s", instrs[inst->opcode]); + INSTR("%s", instr); OPERANDS("%s %s", r2, r1); return true; } -static bool decode_formatII(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatII(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->reg2 = get_reg2(inst); - inst->imm = get_reg1(inst); - inst->byte_size = 2; + switch (inst->opcode) { + case V850_ADD_IMM5: + case V850_CMP_IMM5: + case V850_MOV_IMM5: + case V850_MULH_IMM5: + case V850_SAR_IMM5: + case V850_SATADD_IMM5: + case V850_SHL_IMM5: + case V850_SHR_IMM5: + inst->id = inst->opcode; + inst->imm = get_reg1(inst); + break; + default: + // CALLT + if ((inst->w1 >> 6) == 0x8) { + inst->id = V850_CALLT; + inst->imm = inst->w1 & 0x3f; + break; + } + return false; + } + const char *instr = instrs[inst->id]; const char *r2 = GR_get(inst->reg2); - if (!(r2)) { + if (!(r2 && instr)) { return false; } - INSTR("%s", instrs[inst->opcode]); + INSTR("%s", instr); OPERANDS("%s %d", r2, inst->imm); return true; } -static bool decode_formatIII(V850_Inst *inst, RzBuffer *b) { - inst->opcode = get_opcode(inst, 5, 10); +static bool decode_formatIII(V850_Inst *inst) { + inst->opcode = get_opcode(inst, 7, 10); inst->disp = get_disp8(inst); inst->cond = get_cond(inst); - inst->byte_size = 2; + switch (inst->opcode) { + case 0xb: inst->id = V850_BCOND; break; + default: return false; + } + + const char *cond_s = conds[inst->cond]; + if (!cond_s) { + return false; + } - INSTR("%s", conds[inst->cond]); + INSTR("%s", cond_s); OPERANDS("%d", inst->disp); return true; } -static bool decode_formatIV_1(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatIV_1(V850_Inst *inst) { inst->opcode = get_opcode(inst, 7, 10); - inst->reg2 = get_reg2(inst); inst->disp = inst->w2 & 0x7f; - inst->byte_size = 2; + inst->reg2 = get_reg2(inst); + switch (inst->opcode) { + case 0x6: inst->id = V850_SLDB; break; + case 0x8: + inst->id = V850_SLDH; + inst->disp <<= 1; + break; + case 0x7: inst->id = V850_SSTB; break; + case 0x9: + inst->id = V850_SSTH; + inst->disp <<= 1; + break; + default: { + if (inst->opcode == 0xa) { + if (inst->w1 & 1) { + inst->id = V850_SSTW; + } else { + inst->id = V850_SLDW; + } + inst->disp = (inst->disp & ~1) << 1; + } + break; + } + return false; + } const char *r2 = GR_get(inst->reg2); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r2 && instr)) { return false; } @@ -207,14 +289,21 @@ static bool decode_formatIV_1(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatIV_2(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatIV_2(V850_Inst *inst) { inst->opcode = get_opcode(inst, 4, 10); - inst->reg2 = get_reg2(inst); inst->disp = inst->w2 & 0xf; - inst->byte_size = 2; + inst->reg2 = get_reg2(inst); + switch (inst->opcode) { + case 0x6: inst->id = V850_SLDBU; break; + case 0x7: + inst->id = V850_SLDHU; + inst->disp <<= 1; + break; + default: return false; + } const char *r2 = GR_get(inst->reg2); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r2 && instr)) { return false; } @@ -224,14 +313,21 @@ static bool decode_formatIV_2(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatV(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatV(V850_Inst *inst) { inst->opcode = get_opcode(inst, 6, 10); inst->reg2 = get_reg2(inst); inst->disp = get_disp22(inst); - inst->byte_size = 4; + switch (inst->opcode) { + case 0x1e: inst->id = V850_JARL; break; + case 0x7: + inst->id = V850_SLDHU; + inst->disp <<= 1; + break; + default: return false; + } const char *r2 = GR_get(inst->reg2); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r2 && instr)) { return false; } @@ -246,11 +342,42 @@ static bool decode_formatVI(V850_Inst *inst, RzBuffer *b) { inst->reg1 = get_reg1(inst); inst->reg2 = get_reg2(inst); inst->imm = get_imm16(inst); - inst->byte_size = 4; + switch (inst->opcode) { + case V850_ADDI: + case V850_MOVEA: + case V850_MOVHI: + case V850_MULHI: + case V850_ORI: + case V850_SATSUBI: + case V850_XORI: + case V850_ANDI: inst->id = inst->opcode; break; + default: /*JARL JMP JR MOV*/ + { + switch (inst->w1 >> 5) { + case 0x17: { + if (get_reg1(inst) == 0) { + inst->id = V850_JARL; + } else { + inst->id = V850_JR; + } + break; + } + case 0x37: inst->id = V850_JMP; break; + case 0x31: inst->id = V850_MOV; break; + default: return false; + } + ut16 imm_ = 0; + if (!rz_buf_read_le16_at(b, 4, &imm_)) { + return false; + } + inst->imm |= (st32)(imm_) << 16; + inst->byte_size = 6; + } + } const char *r1 = GR_get(inst->reg1); const char *r2 = GR_get(inst->reg2); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r1 && r2 && instr)) { return false; } @@ -260,16 +387,78 @@ static bool decode_formatVI(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatVII(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatVII(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->reg1 = get_reg1(inst); inst->reg2 = get_reg2(inst); inst->disp = get_imm16(inst); - inst->byte_size = 4; + inst->sub_opcode = inst->w2 & 1; + switch (inst->opcode) { + case 0x38: inst->id = V850_LDB; break; + case 0x3a: inst->id = V850_STB; break; + case 0x3b: + if (!(inst->w2 & 1)) { + inst->id = V850_STH; + } else { + inst->id = V850_STW; + } + inst->disp &= ~1; + break; + case 0x3e: { + if (inst->w2 & 1) { + inst->id = V850_LDBU; + break; + } + return false; + } + case 0x39: { + if (!(inst->w2 & 1)) { + inst->id = V850_LDH; + } else { + inst->id = V850_LDW; + } + inst->disp &= ~1; + break; + } + case 0x37: + if (inst->reg2 == 0 && inst->sub_opcode) { + inst->id = V850_LOOP; + inst->disp &= ~1; + break; + } + return false; + case 0x3f: { + if (inst->reg2 == 0 && inst->sub_opcode) { + inst->id = V850_BCOND; + inst->cond = get_cond(inst); + inst->disp = (inst->disp >> 1) | (((inst->reg2 >> 4) & 1) << 15); + // TODO: + return true; + } + if (inst->reg2 == 0 && extract(inst->w2, 0, 11) == 0x378) { + inst->id = V850_LDLW; + break; + } + if (inst->reg2 == 0 && extract(inst->w2, 0, 11) == 0x37a) { + inst->id = V850_STCW; + break; + } + if (extract(inst->w2, 0, 11) == 0xc4) { + inst->id = V850_ROTL; + break; + } + if (inst->sub_opcode) { + inst->id = V850_LDHU; + break; + } + return false; + } + default: return false; + } const char *r1 = GR_get(inst->reg1); const char *r2 = GR_get(inst->reg2); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r1 && r2 && instr)) { return false; } @@ -279,16 +468,22 @@ static bool decode_formatVII(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatVIII(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatVIII(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->reg1 = get_reg1(inst); - inst->sub = inst->w1 >> 14; + inst->sub_opcode = inst->w1 >> 14; inst->bit = (inst->w1 >> 11) & 0x7; inst->disp = get_imm16(inst); - inst->byte_size = 4; + switch (inst->opcode | (inst->sub_opcode << 6)) { + case 0x38 | (0x2 << 6): inst->id = V850_CLR1; break; + case 0x3e | (0x1 << 6): inst->id = V850_NOT1; break; + case 0x3e | (0x0 << 6): inst->id = V850_SET1; break; + case 0x3e | (0x3 << 6): inst->id = V850_TST1; break; + default: return false; + } const char *r1 = GR_get(inst->reg1); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r1 && instr)) { return false; } @@ -298,14 +493,66 @@ static bool decode_formatVIII(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatIX(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatIX(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); + if (!(inst->w1 & 1)) { + return false; + } + inst->reg1 = get_reg1(inst); inst->reg2 = get_reg2(inst); inst->sub_opcode = get_imm16(inst) & ~1; - inst->byte_size = 4; - const char *instr = instrs[inst->opcode]; + if (inst->opcode == 0x3f) { + if (inst->sub_opcode == 0x00e4) { + inst->id = V850_CLR1; + } else if (inst->sub_opcode == 0x00e2) { + inst->id = V850_NOT1; + } else if (inst->sub_opcode == 0x00e6) { + inst->id = V850_TST1; + } else if (inst->sub_opcode == 0x00a0) { + inst->id = V850_SAR; + } else if (inst->sub_opcode == 0x00b0) { + inst->id = V850_SHL; + } else if (inst->sub_opcode == 0x0080) { + inst->id = V850_SHR; + } else if (extract(inst->opcode, 0, 11) == 0x020) { + inst->id = V850_LDSR; + } else if (extract(inst->opcode, 0, 11) == 0x040) { + inst->id = V850_STSR; + } else if (extract(inst->opcode, 0, 11) == 0x364 && inst->reg1 == 0) { + inst->id = V850_SCH0L; + } else if (extract(inst->opcode, 0, 11) == 0x360 && inst->reg1 == 0) { + inst->id = V850_SCH0R; + } else if (extract(inst->opcode, 0, 11) == 0x366 && inst->reg1 == 0) { + inst->id = V850_SCH1L; + } else if (extract(inst->opcode, 0, 11) == 0x362 && inst->reg1 == 0) { + inst->id = V850_SCH1R; + } else if (extract(inst->sub_opcode, 4, 7) == 0x09 || + extract(inst->sub_opcode, 4, 7) == 0x0b || + extract(inst->sub_opcode, 4, 7) == 0x0d) { + ut8 msb_ = extract(inst->sub_opcode, 12, 4); + ut8 lsb_ = extract(inst->sub_opcode, 1, 3) | extract(inst->sub_opcode, 11, 1) << 3; + // TODO: + inst->id = V850_BINS; + } else { + return false; + } + } else if (inst->opcode == 0x3e) { + if (inst->sub_opcode == 0x0200) { + inst->id = V850_SASF; + } else if (inst->sub_opcode == 0x00e0) { + inst->id = V850_SET1; + } else if (inst->sub_opcode == 0x0000) { + inst->id = V850_SETF; + } else { + return false; + } + } else { + return false; + } + + const char *instr = instrs[inst->id]; if (!(instr)) { return false; } @@ -314,12 +561,16 @@ static bool decode_formatIX(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatX(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatX(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->sub_opcode = (get_imm16(inst) & ~1) | (get_reg2(inst) << 21) | (get_reg1(inst) << 16); - inst->byte_size = 4; - const char *instr = instrs[inst->opcode]; + if ((inst->w1 | (inst->w2 << 16)) == (0xffff | (0xf160 << 16))) { + inst->id = V850_CLL; + } + // TODO: format X + + const char *instr = instrs[inst->id]; if (!(instr)) { return false; } @@ -328,18 +579,17 @@ static bool decode_formatX(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatXI(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatXI(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->reg1 = get_reg1(inst); inst->reg2 = get_reg2(inst); inst->reg3 = get_reg3(inst); inst->sub_opcode = extract(inst->w2, 17, 10); - inst->byte_size = 4; const char *r1 = GR_get(inst->reg1); const char *r2 = GR_get(inst->reg2); const char *r3 = GR_get(inst->reg3); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r1 && r2 && r3 && instr)) { return false; } @@ -349,16 +599,15 @@ static bool decode_formatXI(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatXII(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatXII(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->reg2 = get_reg2(inst); inst->reg3 = get_reg3(inst); inst->sub_opcode = extract(inst->w2, 17, 10) | (get_reg1(inst) << 10); - inst->byte_size = 4; const char *r2 = GR_get(inst->reg2); const char *r3 = GR_get(inst->reg3); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r2 && r3 && instr)) { return false; } @@ -368,15 +617,14 @@ static bool decode_formatXII(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatXIII(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatXIII(V850_Inst *inst) { inst->opcode = get_opcode(inst, 6, 10); inst->sub_opcode = get_reg2(inst); inst->imm = inst->w1 & 0x3f >> 1; inst->list = get_list(inst); inst->reg2 = inst->w2 & 0x1f; - inst->byte_size = 4; - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(instr)) { return false; } @@ -386,7 +634,7 @@ static bool decode_formatXIII(V850_Inst *inst, RzBuffer *b) { return true; } -static bool decode_formatXIV(V850_Inst *inst, RzBuffer *b) { +static bool decode_formatXIV(V850_Inst *inst) { inst->opcode = get_opcode(inst, 5, 10); inst->reg1 = get_reg1(inst); inst->reg3 = get_reg3(inst); @@ -395,7 +643,7 @@ static bool decode_formatXIV(V850_Inst *inst, RzBuffer *b) { const char *r1 = GR_get(inst->reg1); const char *r3 = GR_get(inst->reg3); - const char *instr = instrs[inst->opcode]; + const char *instr = instrs[inst->id]; if (!(r1 && r3 && instr)) { return false; } @@ -417,83 +665,43 @@ int v850_decode_command(const ut8 *bytes, int len, V850_Inst *inst) { if (!rz_buf_read_le16(b, &inst->w1)) { goto err; } - inst->byte_size = -1; - if (inst->w1 == 0) { - inst->byte_size = 2; - inst->opcode = V850_NOP; - snprintf(inst->instr, V850_INSTR_MAXLEN - 1, "%s", "nop"); - return inst->byte_size; + inst->byte_size = 2; + if (!(decode_formatI(inst) || + decode_formatII(inst) || + decode_formatIII(inst) || + decode_formatIV_1(inst) || + decode_formatIV_2(inst))) { + goto err; } - ut8 opcode = get_opcode(inst, 5, 10); - switch (opcode) { - case V850_MOV: - case V850_NOT: - case V850_DIVH: - case V850_JMP: - case V850_SATSUBR: - case V850_SATSUB: - case V850_SATADD: - case V850_MULH: - case V850_OR: - case V850_XOR: - case V850_AND: - case V850_TST: - case V850_SUBR: - case V850_SUB: - case V850_ADD: - case V850_CMP: - decode_formatI(inst, b); - break; - case V850_MOV_IMM5: - case V850_SATADD_IMM5: - case V850_ADD_IMM5: - case V850_CMP_IMM5: - case V850_SHR_IMM5: - case V850_SAR_IMM5: - case V850_SHL_IMM5: - case V850_MULH_IMM5: - decode_formatII(inst, b); - break; - case V850_ADDI: - case V850_MOVEA: - case V850_MOVHI: - case V850_SATSUBI: - case V850_ORI: - case V850_XORI: - case V850_ANDI: - case V850_MULHI: - decode_formatVI(inst, b); - break; - default: { - if (opcode == 0b111010 || - opcode == 0b111011 || - opcode == 0b111000 || - opcode == 0b111001) { - decode_formatVII(inst, b); - } - - if (opcode == 0x3e) { - decode_formatVIII(inst, b); - } - - if (opcode == 0b111111 || - opcode == 0b111110) { - decode_formatIX(inst, b); - } - if ((get_opcode(inst, 5, 10) >> 2) == 0xB) { - decode_formatIII(inst, b); - } + if (!rz_buf_read_le16(b, &inst->w2)) { + goto err; + } + inst->byte_size = 4; + if (!(decode_formatV(inst) || + decode_formatVI(inst, b) || + decode_formatVII(inst) || + decode_formatVIII(inst) || + decode_formatIX(inst) || + decode_formatX(inst) || + decode_formatXI(inst) || + decode_formatXII(inst) || + decode_formatXIII(inst))) { + goto err; + } - ut8 opcj = (inst->w1 >> 6) & 0x1f; - if (opcj == 0b11110) { - decode_formatV(inst, b); - } + if (!rz_buf_read_le16(b, &inst->w3)) { + goto err; } + inst->byte_size = 6; + if (!decode_formatXIV(inst)) { + goto err; } + rz_buf_free(b); return inst->byte_size; err: + inst->byte_size = -1; rz_buf_free(b); return -1; } diff --git a/librz/asm/arch/v850/v850_disas.h b/librz/asm/arch/v850/v850_disas.h index 1f38520411b..872f411847d 100644 --- a/librz/asm/arch/v850/v850_disas.h +++ b/librz/asm/arch/v850/v850_disas.h @@ -35,7 +35,7 @@ typedef enum { V850_SAR_IMM5 = 0x15, V850_SHL_IMM5 = 0x16, V850_MULH_IMM5 = 0x17, - V850_SLDB = 0x18, + V850_SLDB, V850_SSTB = 0x1C, V850_SLDH = 0x20, V850_SSTH = 0x24, @@ -109,7 +109,7 @@ typedef enum { V850_CALLT, V850_CAXI, - V850_CLI, + V850_CLL, V850_CTRET, V850_DI, V850_DISPOSE, @@ -129,7 +129,7 @@ typedef enum { V850_STSR, V850_STCW, V850_SWITCH, - V850_STNCE, + V850_SYNCE, V850_SYNCI, V850_SYNCM, V850_SYNCP, @@ -282,7 +282,6 @@ typedef struct { ut8 reg2 : 5; ut8 reg3 : 5; ut8 cond : 4; - ut8 sub : 2; ut8 bit : 3; ut8 byte_size : 4; ut16 list; @@ -337,7 +336,7 @@ static inline ut16 get_disp22(const V850_Inst *i) { } static inline ut16 get_list(const V850_Inst *i) { - return ((i->w2 & ~0x1f) >> 5) | ((i->w1 & 1) << 11) + return ((i->w2 & ~0x1f) >> 5) | ((i->w1 & 1) << 11); } int v850_decode_command(const ut8 *bytes, int len, V850_Inst *inst);