Skip to content

Commit

Permalink
v850: Add RzAsm and RzAnalysis support for rh850
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Jan 25, 2024
1 parent b32e00f commit 8fe1e80
Show file tree
Hide file tree
Showing 8 changed files with 2,089 additions and 979 deletions.
245 changes: 245 additions & 0 deletions librz/analysis/arch/v850/v850_esil.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
// SPDX-FileCopyrightText: 2012-2020 pancake <[email protected]>
// SPDX-FileCopyrightText: 2014 Fedor Sakharov <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only

static void update_flags(RzStrBuf *out, int flags) {
if (flags & V850_FLAG_CY) {
rz_strbuf_append(out, "31,$c,cy,:=");
}
if (flags & V850_FLAG_OV) {
rz_strbuf_append(out, ",31,$o,ov,:=");
}
if (flags & V850_FLAG_S) {
rz_strbuf_append(out, ",31,$s,s,:=");
}
if (flags & V850_FLAG_Z) {
rz_strbuf_append(out, ",$z,z,:=");
}
}

static void clear_flags(RzStrBuf *out, int flags) {
if (flags & V850_FLAG_CY) {
rz_strbuf_append(out, ",0,cy,=");
}
if (flags & V850_FLAG_OV) {
rz_strbuf_append(out, ",0,ov,=");
}
if (flags & V850_FLAG_S) {
rz_strbuf_append(out, ",0,s,=");
}
if (flags & V850_FLAG_Z) {
rz_strbuf_append(out, ",0,z,=");
}
}

#define R1 GR_get(get_reg1(x))
#define R2 GR_get(get_reg2(x))

static void v850_esil(RzStrBuf *out, V850_Inst *x) {
const char *reg1 = NULL;
const char *reg2 = NULL;
ut32 bitmask = 0;
switch (x->id) {
case V850_MOV_IMM5:
case V850_MOV:
// 2 formats
if (x->id != V850_MOV_IMM5) { // Format I
rz_strbuf_appendf(out, "%s,%s,=", R1, R2);
} else { // Format II
rz_strbuf_appendf(out, "%" PFMT64d ",%s,=", (st64)(x->imm), R2);
}
break;
case V850_MOVEA:
// FIXME: to decide about reading 16/32 bit and use only macros to access
rz_strbuf_appendf(out, "%s,0xffff,&,%u,+,%s,=", R1, x->w2, R2);
break;
case V850_SLDB:
case V850_SLDH:
case V850_SLDW:
case V850_SSTB:
case V850_SSTH:
case V850_SSTW:
break;
case V850_NOT:
rz_strbuf_appendf(out, "%s,0xffffffff,^,%s,=", R1, R2);
update_flags(out, V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_DIVH:
rz_strbuf_appendf(out, "%s,%s,0xffff,&,/,%s,=",
R1, R2, R2);
update_flags(out, V850_FLAG_OV | V850_FLAG_S | V850_FLAG_Z);
break;
case V850_JMP:
rz_strbuf_appendf(out, "%s,pc,=", R1);
break;
case V850_JARL:
// TODO: fix displacement reading
rz_strbuf_appendf(out, "pc,%s,=,pc,%u,+=", R2, x->disp);
break;
case V850_OR:
rz_strbuf_appendf(out, "%s,%s,|=", R1, R2);
update_flags(out, V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_ORI:
rz_strbuf_appendf(out, "%hu,%s,|,%s,=",
x->w2, R1, R2);
update_flags(out, V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_MULH:
case V850_MULH_IMM5:
break;
case V850_XOR:
rz_strbuf_appendf(out, "%s,%s,^=", R1, R2);
update_flags(out, V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_XORI:
rz_strbuf_appendf(out, "%hu,%s,^,%s,=", x->w2, R1, R2);
update_flags(out, V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_AND:
rz_strbuf_appendf(out, "%s,%s,&=", R1, R2);
update_flags(out, V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_ANDI:
rz_strbuf_appendf(out, "%hu,%s,&,%s,=", x->w2, R1, R2);
update_flags(out, V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV | V850_FLAG_S);
break;
case V850_CMP:
rz_strbuf_appendf(out, "%s,%s,==", R1, R2);
update_flags(out, -1);
break;
case V850_CMP_IMM5:
rz_strbuf_appendf(out, "%d,%s,==", x->imm, R2);
update_flags(out, -1);
break;
case V850_TST:
rz_strbuf_appendf(out, "%s,%s,&", R1, R2);
update_flags(out, V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_SUB:
rz_strbuf_appendf(out, "%s,%s,-=", R1, R2);
update_flags(out, -1);
break;
case V850_SUBR:
rz_strbuf_appendf(out, "%s,%s,-,%s=", R2, R1, R2);
update_flags(out, -1);
break;
case V850_ADD:
rz_strbuf_appendf(out, "%s,%s,+=", R1, R2);
update_flags(out, -1);
break;
case V850_ADD_IMM5:
rz_strbuf_appendf(out, "%d,%s,+=", (st8)x->imm, R2);
update_flags(out, -1);
break;
case V850_ADDI:
rz_strbuf_appendf(out, "%d,%s,+,%s,=", (st32)x->w2, R1, R2);
update_flags(out, -1);
break;
case V850_SHR_IMM5:
rz_strbuf_appendf(out, "%u,%s,>>=", x->imm, R2);
update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_SAR_IMM5: {
ut16 imm5 = x->imm;
reg2 = R2;
rz_strbuf_appendf(out, "31,%s,>>,?{,%u,32,-,%u,1,<<,--,<<,}{,0,},%u,%s,>>,|,%s,=", reg2, (ut8)imm5, (ut8)imm5, (ut8)imm5, reg2, reg2);
update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
}
case V850_SHL_IMM5:
rz_strbuf_appendf(out, "%u,%s,<<=", x->imm, R2);
update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_BCOND:
switch (x->cond) {
case V850_COND_BV:
rz_strbuf_appendf(out, "ov");
break;
case V850_COND_BL:
rz_strbuf_appendf(out, "cy");
break;
case V850_COND_BE:
rz_strbuf_appendf(out, "z");
break;
case V850_COND_BNH:
rz_strbuf_appendf(out, "cy,z,|");
break;
case V850_COND_BN:
rz_strbuf_appendf(out, "s");
break;
case V850_COND_BR: // Always
rz_strbuf_appendf(out, "1");
break;
case V850_COND_BLT:
rz_strbuf_appendf(out, "s,ov,^");
break;
case V850_COND_BLE:
rz_strbuf_appendf(out, "s,ov,^,z,|");
break;
case V850_COND_BNV:
rz_strbuf_appendf(out, "ov,!");
break;
case V850_COND_BNL:
rz_strbuf_appendf(out, "cy,!");
break;
case V850_COND_BNE:
rz_strbuf_appendf(out, "z,!");
break;
case V850_COND_BH:
rz_strbuf_appendf(out, "cy,z,|,!");
break;
case V850_COND_BP:
rz_strbuf_appendf(out, "s,!");
break;
case V850_COND_BGE:
rz_strbuf_appendf(out, "s,ov,^,!");
break;
case V850_COND_BGT:
rz_strbuf_appendf(out, "s,ov,^,z,|,!");
break;
}
rz_strbuf_appendf(out, ",?{,$$,%llu,+,pc,=,}", x->addr + x->disp);
break;
case V850_CLR1:
bitmask = (1 << x->bit);
rz_strbuf_appendf(out, "%hu,%s,+,[1],%u,&,%hu,%s,+,=[1]", x->w2, R1, bitmask, x->w2, R1);
// TODO: Read the value of the memory byte and set zero flag accordingly!
break;
case V850_NOT1:
bitmask = (1 << x->bit);
rz_strbuf_appendf(out, "%hu,%s,+,[1],%u,^,%hu,%s,+,=[1]", x->w2, R1, bitmask, x->w2, R1);
// TODO: Read the value of the memory byte and set zero flag accordingly!
break;

case V850_SHL:
rz_strbuf_appendf(out, "%s,%s,<<=", R1, R2);
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,>>=", R1, R2);
update_flags(out, V850_FLAG_CY | V850_FLAG_S | V850_FLAG_Z);
clear_flags(out, V850_FLAG_OV);
break;
case V850_SAR:
reg1 = R1;
reg2 = R2;
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;
}
}
Loading

0 comments on commit 8fe1e80

Please sign in to comment.