From 26f01a5bdb38d7e085ce4aa0f9ddb81c85523b46 Mon Sep 17 00:00:00 2001 From: "Dr. Christian Giessen" Date: Mon, 27 Apr 2026 09:06:34 +0000 Subject: [PATCH] Add analysis support: op->type for all instruction types Every decode path now sets op->type for r2 analysis: - R_ANAL_OP_TYPE_NOP/TRAP: NOP, IDLE - R_ANAL_OP_TYPE_MUL: MAC operations (Type 1, 8, 9) - R_ANAL_OP_TYPE_ADD: ALU operations (Type 1, 8, 9), MODIFY - R_ANAL_OP_TYPE_MOV: register loads (Type 6, 7, 17, 18, 25, 33) - R_ANAL_OP_TYPE_LOAD/STORE: memory access (Type 3, 4, 12, 29, 32) - R_ANAL_OP_TYPE_JMP/CJMP/CALL: jumps and calls (Type 10, 10a, 19, 36) - R_ANAL_OP_TYPE_RET: RTS/RTI (Type 20) - R_ANAL_OP_TYPE_REP: DO UNTIL loops (Type 11) - R_ANAL_OP_TYPE_SHR: shift operations (Type 14, 15, 16) - R_ANAL_OP_TYPE_DIV: DIVQ/DIVS (Type 23, 24) - R_ANAL_OP_TYPE_PUSH: Push/Pop/Cache (Type 26) - R_ANAL_OP_TYPE_IO: IO/System register (Type 34, 35) - R_ANAL_OP_TYPE_SWI: SETINT/CLRINT (Type 37) op->jump set for all branch types. op->fail set for conditional jumps (next instruction). Enables: af (function analysis), pdf (function disassembly), agf (control flow graph), VV (visual graph mode). Tested: FIR and IIR functions recognized correctly. --- r2plugin/asm_adsp219x.c | 142 +++++++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 39 deletions(-) diff --git a/r2plugin/asm_adsp219x.c b/r2plugin/asm_adsp219x.c index c7430d2..55ffd61 100644 --- a/r2plugin/asm_adsp219x.c +++ b/r2plugin/asm_adsp219x.c @@ -1,11 +1,11 @@ -/* asm_adsp219x.c -- Radare2 arch plugin for Analog Devices ADSP-219x +/* asm_adsp219x.c -- Radare2 arch+anal plugin for Analog Devices ADSP-219x Author: Dr. Christian Giessen - Date: 2026 + Copyright (C) 2026 Dr. Christian Giessen - Decodes all documented ADSP-219x instruction types (Types 1-37). - Most types are verified against open21xx assembler output; see - TESTING.md for the current verification matrix and any remaining - structural-only cases. */ + Decodes all documented ADSP-219x instruction types (Types 1-37) + with op->type annotations for analysis, function detection, and + control flow graphing. Most types verified against open21xx + assembler output; see TESTING.md for the verification matrix. */ #include @@ -101,6 +101,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("%s, %s=DM(I%d+=M%d), %s=PM(I%d+=M%d)", f, reg0[dd], dmi, dmm, reg0[pd + 4], pmi + 4, pmm + 4); + op->type = (amf < 16) ? R_ANAL_OP_TYPE_MUL : R_ANAL_OP_TYPE_ADD; return true; } @@ -115,11 +116,17 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) const char *rname = ((ins >> 21) & 1) ? reg1[reg] : reg0[reg]; if (d) - op->mnemonic = r_str_newf ("DM(0x%04X) = %s", - addr, rname); + { + op->mnemonic = r_str_newf ("DM(0x%04X) = %s", + addr, rname); + op->type = R_ANAL_OP_TYPE_STORE; + } else - op->mnemonic = r_str_newf ("%s = DM(0x%04X)", - rname, addr); + { + op->mnemonic = r_str_newf ("%s = DM(0x%04X)", + rname, addr); + op->type = R_ANAL_OP_TYPE_LOAD; + } return true; } @@ -138,13 +145,19 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) ut32 mreg = (ins & 3) | (g ? 4 : 0); char mem = g ? 'P' : 'D'; if (d) - op->mnemonic = r_str_newf ("%s, %cM(I%d += M%d) = %s", - f, mem, ireg, mreg, - reg0[dreg]); + { + op->mnemonic = r_str_newf ("%s, %cM(I%d += M%d) = %s", + f, mem, ireg, mreg, + reg0[dreg]); + op->type = R_ANAL_OP_TYPE_STORE; + } else - op->mnemonic = r_str_newf ("%s, %s = %cM(I%d += M%d)", - f, reg0[dreg], mem, - ireg, mreg); + { + op->mnemonic = r_str_newf ("%s, %s = %cM(I%d += M%d)", + f, reg0[dreg], mem, + ireg, mreg); + op->type = R_ANAL_OP_TYPE_LOAD; + } return true; } @@ -188,6 +201,8 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("%s = %s(%s, %s)", dst, f, reg0[xreg], reg0[yreg]); + op->type = (amf < 16) ? R_ANAL_OP_TYPE_MUL + : R_ANAL_OP_TYPE_ADD; return true; } @@ -202,6 +217,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) { op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s^2)", cp, cs, sp, dst, f, x); + op->type = R_ANAL_OP_TYPE_MUL; return true; } @@ -210,6 +226,8 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) { op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s, 0)", cp, cs, sp, dst, f, x); + op->type = (amf < 16) ? R_ANAL_OP_TYPE_MUL + : R_ANAL_OP_TYPE_ADD; return true; } @@ -220,6 +238,8 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) : yop_alu[yop_i]; op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s, %s)", cp, cs, sp, dst, f, x, y); + op->type = (amf < 16) ? R_ANAL_OP_TYPE_MUL + : R_ANAL_OP_TYPE_ADD; return true; } @@ -288,21 +308,23 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("%s(%s, %s), %s = %s", f, x, y, reg0[ddreg], reg0[sdreg]); + op->type = (amf < 16) ? R_ANAL_OP_TYPE_MUL + : R_ANAL_OP_TYPE_ADD; return true; } /* Type 6/7/IO/System (010xxx / 011xxx) */ if (b23_22 == 1) { - if (b21_20 == 0) { op->mnemonic = r_str_newf ("%s = 0x%04X", reg0[ins&0xF], (ins>>4)&0xFFFF); return true; } /* Type 6 */ - if (b21_20 == 1) { op->mnemonic = r_str_newf ("%s = 0x%04X", reg1[ins&0xF], (ins>>4)&0xFFFF); return true; } /* Type 7 */ + if (b21_20 == 0) { op->mnemonic = r_str_newf ("%s = 0x%04X", reg0[ins&0xF], (ins>>4)&0xFFFF); op->type = R_ANAL_OP_TYPE_MOV; return true; } /* Type 6 */ + if (b21_20 == 1) { op->mnemonic = r_str_newf ("%s = 0x%04X", reg1[ins&0xF], (ins>>4)&0xFFFF); op->type = R_ANAL_OP_TYPE_MOV; return true; } /* Type 7 */ /* Type 34 and 35 are in the b23_22==0 block below */ } /* Type 8/9/10/11/17... (00xxxx) */ if (b23_22 == 0) { - if (b21_20 == 3) { op->mnemonic = r_str_newf ("%s = 0x%04X", reg2[ins&0xF], (ins>>4)&0xFFFF); return true; } /* Type 7 (Reg2) */ + if (b21_20 == 3) { op->mnemonic = r_str_newf ("%s = 0x%04X", reg2[ins&0xF], (ins>>4)&0xFFFF); op->type = R_ANAL_OP_TYPE_MOV; return true; } /* Type 7 (Reg2) */ /* Type 36: Long Jump/Call (2-word, bits 23-16 = 00000101) */ if ((ins >> 16) == 0x05) @@ -416,6 +438,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) b_bit ? " (DB)" : ""); op->type = R_ANAL_OP_TYPE_CJMP; op->jump = target; + op->fail = op->addr + 3; return true; } /* Type 17: Reg = Reg (bits 23-16 = 00001101) */ @@ -424,6 +447,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("%s = %s", get_reg ((ins >> 10) & 3, (ins >> 4) & 0xF), get_reg ((ins >> 8) & 3, ins & 0xF)); + op->type = R_ANAL_OP_TYPE_MOV; return true; } @@ -469,6 +493,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) sf_names[sf], xop_shift[xop_i], reg0[dreg], g ? 'P' : 'D', ireg + base, mreg + base); + op->type = d ? R_ANAL_OP_TYPE_STORE : R_ANAL_OP_TYPE_LOAD; return true; } @@ -484,6 +509,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("%s %s, %s = %s", sf_names[sf], reg0[xreg], reg0[ddreg], reg0[sdreg]); + op->type = R_ANAL_OP_TYPE_SHR; return true; } @@ -502,6 +528,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("IF %s SR = %s %s", cond_str[cond], sf_names[sf], reg0[xreg]); + op->type = R_ANAL_OP_TYPE_SHR; return true; } @@ -516,6 +543,8 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ( "DO 0x%06" PFMT64x " UNTIL %s", target, cond_str[term]); + op->type = R_ANAL_OP_TYPE_REP; + op->jump = target; return true; } @@ -528,6 +557,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("SR = %s %s BY %d", sf_names[sf], reg0[xreg], exp); + op->type = R_ANAL_OP_TYPE_SHR; return true; } @@ -552,6 +582,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) } op->mnemonic = pos ? strdup (buf) : strdup ("MODE NOP"); + op->type = R_ANAL_OP_TYPE_MOV; return true; } @@ -561,6 +592,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) ut32 r = (ins >> 13) & 1; op->mnemonic = r_str_newf ("SAT %s", r ? "SR" : "MR"); + op->type = R_ANAL_OP_TYPE_MOV; return true; } @@ -571,6 +603,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) ut32 reg = ins & 0xF; op->mnemonic = r_str_newf ("%s = 0x%03X", reg3[reg], data); + op->type = R_ANAL_OP_TYPE_MOV; return true; } @@ -608,6 +641,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) int base = g ? 4 : 0; op->mnemonic = r_str_newf ("MODIFY(I%d += M%d)", ireg + base, mreg + base); + op->type = R_ANAL_OP_TYPE_ADD; return true; } @@ -617,6 +651,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) ut32 xop_i = (ins >> 8) & 0x7; op->mnemonic = r_str_newf ("DIVQ %s", xop_alu[xop_i]); + op->type = R_ANAL_OP_TYPE_DIV; return true; } @@ -628,6 +663,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) op->mnemonic = r_str_newf ("DIVS %s, %s", yop_alu[yop_i], xop_alu[xop_i]); + op->type = R_ANAL_OP_TYPE_DIV; return true; } @@ -669,6 +705,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) pos ? ", " : ""); op->mnemonic = pos ? strdup (buf) : strdup ("STACK NOP"); + op->type = R_ANAL_OP_TYPE_PUSH; return true; } @@ -691,13 +728,19 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) int base = g ? 4 : 0; const char *op_str = u ? "+=" : "+"; if (d) - op->mnemonic = r_str_newf ("DM(I%d %s %d) = %s", - ireg + base, op_str, smod, - reg0[dreg]); + { + op->mnemonic = r_str_newf ("DM(I%d %s %d) = %s", + ireg + base, op_str, smod, + reg0[dreg]); + op->type = R_ANAL_OP_TYPE_STORE; + } else - op->mnemonic = r_str_newf ("%s = DM(I%d %s %d)", - reg0[dreg], ireg + base, op_str, - smod); + { + op->mnemonic = r_str_newf ("%s = DM(I%d %s %d)", + reg0[dreg], ireg + base, op_str, + smod); + op->type = R_ANAL_OP_TYPE_LOAD; + } return true; } @@ -719,13 +762,19 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) const char *mod = u_bit ? "+=" : "+"; const char *rname = get_reg (rgp, reg); if (d) - op->mnemonic = r_str_newf ("%s(I%d %s M%d) = %s", - mem, ireg + base, mod, mreg + base, - rname); + { + op->mnemonic = r_str_newf ("%s(I%d %s M%d) = %s", + mem, ireg + base, mod, mreg + base, + rname); + op->type = R_ANAL_OP_TYPE_STORE; + } else - op->mnemonic = r_str_newf ("%s = %s(I%d %s M%d)", - rname, mem, ireg + base, mod, - mreg + base); + { + op->mnemonic = r_str_newf ("%s = %s(I%d %s M%d)", + rname, mem, ireg + base, mod, + mreg + base); + op->type = R_ANAL_OP_TYPE_LOAD; + } return true; } @@ -752,6 +801,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) "DM(I%d %s M%d) = %s, %s = I%d", ireg + base, mod, mreg + base, rname, rname, ireg + base); + op->type = R_ANAL_OP_TYPE_STORE; return true; } @@ -764,6 +814,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) int base = g ? 4 : 0; op->mnemonic = r_str_newf ("MODIFY(I%d += %d)", ireg + base, mod); + op->type = R_ANAL_OP_TYPE_ADD; return true; } @@ -775,11 +826,17 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) ut32 addr = (addr_hi << 8) | ((ins >> 4) & 0xFF); ut32 dreg = ins & 0xF; if (d) - op->mnemonic = r_str_newf ("IO(0x%03X) = %s", - addr, reg0[dreg]); + { + op->mnemonic = r_str_newf ("IO(0x%03X) = %s", + addr, reg0[dreg]); + op->type = R_ANAL_OP_TYPE_IO; + } else - op->mnemonic = r_str_newf ("%s = IO(0x%03X)", - reg0[dreg], addr); + { + op->mnemonic = r_str_newf ("%s = IO(0x%03X)", + reg0[dreg], addr); + op->type = R_ANAL_OP_TYPE_IO; + } return true; } /* Type 35: Sys ctrl reg (bits 23-16 = 00000110, bit15=0) */ @@ -789,11 +846,17 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) ut32 addr = (ins >> 4) & 0xFF; ut32 dreg = ins & 0xF; if (d) - op->mnemonic = r_str_newf ("REG(0x%02X) = %s", - addr, reg0[dreg]); + { + op->mnemonic = r_str_newf ("REG(0x%02X) = %s", + addr, reg0[dreg]); + op->type = R_ANAL_OP_TYPE_IO; + } else - op->mnemonic = r_str_newf ("%s = REG(0x%02X)", - reg0[dreg], addr); + { + op->mnemonic = r_str_newf ("%s = REG(0x%02X)", + reg0[dreg], addr); + op->type = R_ANAL_OP_TYPE_IO; + } return true; } @@ -804,6 +867,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask) ut32 bit = ins & 0xF; op->mnemonic = r_str_newf ("%s %d", c ? "CLRINT" : "SETINT", bit); + op->type = R_ANAL_OP_TYPE_SWI; return true; } }