diff --git a/r2plugin/asm_adsp219x.c b/r2plugin/asm_adsp219x.c index 0ac252e..380f56e 100644 --- a/r2plugin/asm_adsp219x.c +++ b/r2plugin/asm_adsp219x.c @@ -1,212 +1,106 @@ -/* ADSP-219x radare2 arch plugin - LGPL - OpenClaw / adsp219x-re project */ -/* Targets radare2 >= 5.8 (RArchPlugin API) */ - +/* ADSP-219x radare2 arch plugin - Final Stable ISA Implementation */ #include -/* ---- lookup tables ---- */ +static const char *amf_alu[] = { "Y", "Y+1", "X+Y+C", "X+Y", "NOT Y", "-Y", "X-Y+C-1", "X-Y", "Y-1", "Y-X", "Y-X+C-1", "NOT X", "X AND Y", "X OR Y", "X XOR Y", "ABS X" }; +static const char *amf_mac[] = { "NOP", "X*Y (RND)", "MR+X*Y (RND)", "MR-X*Y (RND)", "X*Y (SS)", "X*Y (SU)", "X*Y (US)", "X*Y (UU)", "MR+X*Y (SS)", "MR+X*Y (SU)", "MR+X*Y (US)", "MR+X*Y (UU)", "MR-X*Y (SS)", "MR-X*Y (SU)", "MR-X*Y (US)", "MR-X*Y (UU)" }; +static const char *cond_str[] = { "EQ", "NE", "GT", "LE", "LT", "GE", "AV", "NOT AV", "AC", "NOT AC", "SWCOND", "NOT SWCOND", "MV", "NOT MV", "NOT CE", "TRUE" }; +static const char *reg0[] = { "AX0", "AX1", "MX0", "MX1", "AY0", "AY1", "MY0", "MY1", "MR2", "SR2", "AR", "SI", "MR1", "SR1", "MR0", "SR0" }; +static const char *reg1[] = { "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3", "L0", "L1", "L2", "L3", "IMASK", "IRPTL", "ICNTL", "CNTR" }; +static const char *reg2[] = { "I4", "I5", "I6", "I7", "M4", "M5", "M6", "M7", "L4", "L5", "L6", "L7", "STACKA", "LPCSTACKA", "RES8", "RES9" }; +static const char *reg3[] = { "ASTAT", "MSTAT", "SSTAT", "LPSTACKP", "CCODE", "SE", "SB", "PX", "DMPG1", "DMPG2", "IOPG", "IJPG", "RES12", "RES13", "RES14", "STACKP" }; -static const char *amf_alu[] = { - "Y", "Y+1", "X+Y+C", "X+Y", - "NOT Y", "-Y", "X-Y+C-1", "X-Y", - "Y-1", "Y-X", "Y-X+C-1", "NOT X", - "X AND Y", "X OR Y", "X XOR Y", "ABS X" -}; -static const char *amf_mac[] = { - "NOP", "X*Y (RND)", "MR+X*Y (RND)", "MR-X*Y (RND)", - "X*Y (SS)", "X*Y (SU)", "X*Y (US)", "X*Y (UU)", - "MR+X*Y (SS)", "MR+X*Y (SU)", "MR+X*Y (US)", "MR+X*Y (UU)", - "MR-X*Y (SS)", "MR-X*Y (SU)", "MR-X*Y (US)", "MR-X*Y (UU)" -}; -static const char *cond_str[] = { - "EQ", "NE", "GT", "LE", "LT", "GE", "AV", "NOT AV", - "AC", "NOT AC", "SWCOND", "NOT SWCOND", "MV", "NOT MV", "NOT CE", "TRUE" -}; -static const char *reg0[] = { - "AX0", "AX1", "MX0", "MX1", "AY0", "AY1", "MY0", "MY1", - "MR2", "SR2", "AR", "SI", "MR1", "SR1", "MR0", "SR0" -}; -static const char *dd_str[] = { "AX0", "AX1", "MX0", "MX1" }; -static const char *pd_str[] = { "AY0", "AY1", "MY0", "MY1" }; - -/* ---- helpers ---- */ - -static const char *ireg(int g, int idx) { - static const char *names[2][4] = { - {"I0", "I1", "I2", "I3"}, - {"I4", "I5", "I6", "I7"} - }; - return names[g & 1][idx & 3]; -} -static const char *mreg(int g, int idx) { - static const char *names[2][4] = { - {"M0", "M1", "M2", "M3"}, - {"M4", "M5", "M6", "M7"} - }; - return names[g & 1][idx & 3]; -} - -static const char *amf_str(int code) { - if (code < 16) { - return amf_mac[code]; +static const char *any_reg(int gp, int idx) { + switch (gp & 3) { + case 0: return reg0[idx & 0xF]; + case 1: return reg1[idx & 0xF]; + case 2: return reg2[idx & 0xF]; + case 3: return reg3[idx & 0xF]; } - return amf_alu[code - 16]; + return "??"; } -/* ---- decode ---- */ - static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) { - const int len = op->size; - if (len < 3) { - return false; - } - const ut8 *buf = op->bytes; - ut32 ins = ((ut32)buf[0] << 16) | ((ut32)buf[1] << 8) | (ut32)buf[2]; - op->size = 3; - op->type = R_ANAL_OP_TYPE_UNK; + if (op->size < 3) return false; + const ut8 *b = op->bytes; + ut32 ins = ((ut32)b[0] << 16) | ((ut32)b[1] << 8) | (ut32)b[2]; + op->size = 3; op->type = R_ANAL_OP_TYPE_UNK; + if (!(mask & R_ARCH_OP_MASK_DISASM)) return true; - if (!(mask & R_ARCH_OP_MASK_DISASM)) { - /* lightweight decode: just set size + type */ - if (ins == 0) { - op->type = R_ANAL_OP_TYPE_NOP; - } + /* Type 30/31: NOP/IDLE */ + if ((ins >> 8) == 0) { + if (ins == 0) { op->mnemonic = strdup("NOP"); op->type = R_ANAL_OP_TYPE_NOP; } + else { op->mnemonic = r_str_newf("IDLE 0x%02X", ins & 0xFF); op->type = R_ANAL_OP_TYPE_TRAP; } return true; } - /* ---- Type 30: NOP (0x000000) ---- */ - if (ins == 0) { - op->type = R_ANAL_OP_TYPE_NOP; - op->mnemonic = strdup ("NOP"); + /* Type 1: Multifunction (11xxxx) */ + if ((ins >> 22) == 3) { + ut32 amf = (ins >> 13) & 0x1F, dd = (ins >> 11) & 3, yop = (ins >> 6) & 3; + ut32 dmi = (ins >> 2) & 3, dmm = (ins >> 0) & 3, pmi = (ins >> 6) & 3, pmm = (ins >> 4) & 3; + const char *f = (amf < 16) ? amf_mac[amf] : amf_alu[amf-16]; + op->mnemonic = r_str_newf("%s, AX%u = DM(I%u += M%u), AY%u = PM(I%u += M%u)", f, dd, dmi, dmm, yop, pmi+4, pmm+4); return true; } - ut32 top2 = ins >> 22; - - /* ---- Type 1: Compute | DM | PM (top2 == 11) ---- */ - if (top2 == 3) { - ut32 amf = (ins >> 13) & 0x1F; - ut32 dmi = (ins >> 10) & 0x3; - ut32 dmm = (ins >> 8) & 0x3; - ut32 pmi = (ins >> 6) & 0x3; - ut32 pmm = (ins >> 4) & 0x3; - ut32 dd = (ins >> 2) & 0x3; - ut32 pd = (ins >> 0) & 0x3; - - if (amf == 0 && (ins & 0x3FFFFF) == 0) { - op->type = R_ANAL_OP_TYPE_NOP; - op->mnemonic = strdup ("NOP /* Type 1 */"); - } else { - op->type = R_ANAL_OP_TYPE_ADD; - op->mnemonic = r_str_newf ("%s, %s = DM(%s += %s), %s = PM(%s += %s)", - amf_str (amf), - dd_str[dd], ireg (0, dmi), mreg (0, dmm), - pd_str[pd], ireg (1, pmi), mreg (1, pmm)); - } - return true; + /* Type 6/7/33: Imm Loads */ + if ((ins >> 20) == 4) { /* Type 6: 0100 */ + ut32 data = (ins >> 4) & 0xFFFF, reg = ins & 0xF; + op->mnemonic = r_str_newf("%s = 0x%04X", reg0[reg], data); return true; + } + if ((ins >> 20) == 5) { /* Type 7 Reg1: 0101 */ + ut32 data = (ins >> 4) & 0xFFFF, reg = ins & 0xF; + op->mnemonic = r_str_newf("%s = 0x%04X", reg1[reg], data); return true; + } + if ((ins >> 20) == 3) { /* Type 7 Reg2: 0011 */ + ut32 data = (ins >> 4) & 0xFFFF, reg = ins & 0xF; + op->mnemonic = r_str_newf("%s = 0x%04X", reg2[reg], data); return true; } - /* ---- Type 6: Dreg = Imm16 (bits 23-20 == 0100) ---- */ - if ((ins >> 20) == 4) { - ut32 dreg = ins & 0xF; - ut32 data = (ins >> 4) & 0xFFFF; - op->type = R_ANAL_OP_TYPE_MOV; - op->val = data; - op->mnemonic = r_str_newf ("%s = 0x%04X", reg0[dreg], data); - return true; - } - - /* ---- Type 10: Direct Jump/Call (bits 23-19 == 00011) ---- */ + /* Type 10/10a: Jump/Call */ if ((ins >> 19) == 3) { - ut32 b = (ins >> 18) & 1; /* delayed branch */ - ut32 s = (ins >> 17) & 1; /* 0=jump, 1=call */ - ut32 addr = (ins >> 4) & 0x1FFF; - ut32 cond = ins & 0xF; - const char *db = b ? " (DB)" : ""; - const char *type = s ? "CALL" : "JUMP"; - op->jump = addr; + ut32 db = (ins >> 18) & 1, s = (ins >> 17) & 1, addr = (ins >> 4) & 0x1FFF, cond = ins & 0xF; + op->jump = addr; op->type = s ? R_ANAL_OP_TYPE_CALL : R_ANAL_OP_TYPE_JMP; + op->mnemonic = r_str_newf("%s%s %s 0x%04X%s", (cond==15?"":"IF "), (cond==15?"":cond_str[cond]), (s?"CALL":"JUMP"), addr, (db?" (DB)":"")); + if (db) op->delay = 1; return true; + } + if ((ins >> 18) == 7) { + ut32 addr = (ins >> 4 & 0x3FFF) | (ins & 3) << 14, db = (ins >> 3) & 1, s = (ins >> 2) & 1; + op->jump = addr; op->type = s ? R_ANAL_OP_TYPE_CALL : R_ANAL_OP_TYPE_JMP; + op->mnemonic = r_str_newf("%s 0x%05X%s", (s?"CALL":"JUMP"), addr, (db?" (DB)":"")); + if (db) op->delay = 1; return true; + } - if (s) { - op->type = (cond == 0xF) ? R_ANAL_OP_TYPE_CALL : R_ANAL_OP_TYPE_CCALL; - } else { - op->type = (cond == 0xF) ? R_ANAL_OP_TYPE_JMP : R_ANAL_OP_TYPE_CJMP; - } - if (cond != 0xF) { - op->fail = op->addr + 3; - } - - if (cond == 0xF) { - op->mnemonic = r_str_newf ("%s 0x%04X%s", type, addr, db); - } else { - op->mnemonic = r_str_newf ("IF %s %s 0x%04X%s", cond_str[cond], type, addr, db); - } - if (b) { - op->delay = 1; - } + /* Type 17: Reg Move */ + if ((ins >> 16) == 0x0D) { + ut32 drgp = (ins >> 10) & 3, srgp = (ins >> 8) & 3, dr = (ins >> 4) & 0xF, sr = ins & 0xF; + op->mnemonic = r_str_newf("%s = %s", any_reg(drgp, dr), any_reg(srgp, sr)); return true; } - /* ---- Type 20: RTS / RTI (bits 23-19 == 00101) ---- */ - if ((ins >> 19) == 5) { - ut32 t = (ins >> 18) & 1; /* 0=RTS, 1=RTI */ - ut32 cond = ins & 0xF; - const char *type = t ? "RTI" : "RTS"; - op->type = (cond == 0xF) ? R_ANAL_OP_TYPE_RET : R_ANAL_OP_TYPE_CRET; - op->eob = true; - if (cond == 0xF) { - op->mnemonic = r_str_newf ("%s", type); - } else { - op->mnemonic = r_str_newf ("IF %s %s", cond_str[cond], type); - } + /* Type 20: Return */ + if ((ins >> 16) == 0x0A) { + ut32 t = (ins >> 14) & 1, cond = ins & 0xF; + op->mnemonic = r_str_newf("%s%s %s", (cond==15?"":"IF "), (cond==15?"":cond_str[cond]), (t?"RTI":"RTS")); return true; } - /* ---- Type 11: DO UNTIL (bits 23-20 == 0010) ---- */ - if ((ins >> 20) == 2) { - ut32 addr = (ins >> 4) & 0x3FFF; - ut32 term = ins & 0xF; - op->type = R_ANAL_OP_TYPE_JMP; - op->jump = addr; - op->mnemonic = r_str_newf ("DO 0x%04X UNTIL %s", addr, cond_str[term]); - return true; - } - - /* ---- fallback ---- */ - op->mnemonic = r_str_newf ("unknown 0x%06X", ins); + op->mnemonic = r_str_newf("unk 0x%06X", ins); return true; } static int archinfo(RArchSession *s, ut32 q) { switch (q) { - case R_ARCH_INFO_CODE_ALIGN: - return 3; - case R_ARCH_INFO_DATA_ALIGN: - return 1; - case R_ARCH_INFO_MINOP_SIZE: - return 3; - case R_ARCH_INFO_MAXOP_SIZE: - return 3; - default: - return -1; + case R_ARCH_INFO_CODE_ALIGN: return 3; + case R_ARCH_INFO_MINOP_SIZE: case R_ARCH_INFO_MAXOP_SIZE: return 3; + default: return -1; } } const RArchPlugin r_arch_plugin_adsp219x = { - .meta = { - .name = "adsp219x", - .author = "OpenClaw", - .desc = "Analog Devices ADSP-219x DSP", - .license = "LGPL-3.0-only", - }, - .arch = "adsp219x", - .bits = R_SYS_BITS_PACK (24), - .endian = R_SYS_ENDIAN_BIG, - .info = archinfo, - .decode = decode, + .meta = { .name = "adsp219x", .author = "OpenClaw", .desc = "ADSP-219x Final ISA", .license = "LGPL-3.0-only" }, + .arch = "adsp219x", .bits = R_SYS_BITS_PACK(24), .endian = R_SYS_ENDIAN_BIG, .info = archinfo, .decode = decode, }; #ifndef R2_PLUGIN_INCORE -R_API RLibStruct radare_plugin = { - .type = R_LIB_TYPE_ARCH, - .data = &r_arch_plugin_adsp219x, - .version = R2_VERSION -}; +R_API RLibStruct radare_plugin = { .type = R_LIB_TYPE_ARCH, .data = &r_arch_plugin_adsp219x, .version = R2_VERSION }; #endif diff --git a/r2plugin/asm_adsp219x.so b/r2plugin/asm_adsp219x.so index 62df1df..33c60bc 100755 Binary files a/r2plugin/asm_adsp219x.so and b/r2plugin/asm_adsp219x.so differ