Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v850: Add RzAsm and RzAnalysis support for rh850 #4151

Merged
merged 2 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading