-
-
Notifications
You must be signed in to change notification settings - Fork 357
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v850: Add RzAsm and RzAnalysis support for rh850
- Loading branch information
Showing
8 changed files
with
2,089 additions
and
979 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.