#include #include /* ADSP-219x 24-bit Opcode Table (Basic definitions) */ static const char *AXOP[] = {"AX0", "AX1", "AR", "MR0", "MR1", "MR2", "SR0", "SR1"}; static const char *AYOP[] = {"AY0", "AY1", "AF", "0"}; static const char *COND[] = {"EQ", "NE", "GT", "LE", "LT", "GE", "AV", "NAV", "AC", "NAC", "SWCOND", "NSWCOND", "MV", "NMV", "NCE", "TRUE"}; static int adsp219x_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { if (len < 3) return -1; ut32 ins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; op->size = 3; /* Simplified decoding for the r2-Backend */ // Type 1: Compute (11xxxxxx) if ((ins >> 22) == 0b11) { ut32 amf = (ins >> 13) & 0x1F; ut32 xop = (ins >> 8) & 0x7; ut32 yop = (ins >> 11) & 0x3; if (amf == 0) r_strbuf_setf(&op->buf_asm, "NOP"); else if (amf >= 0x10) r_strbuf_setf(&op->buf_asm, "COMPUTE (ALU:%d, %s, %s)", amf, AXOP[xop], AYOP[yop]); else r_strbuf_setf(&op->buf_asm, "COMPUTE (MAC:%d, %s, %s)", amf, AXOP[xop], AYOP[yop]); } // Type 6: Dreg = Imm16 (0100xxxx) else if ((ins >> 20) == 0b0100) { ut32 dreg = ins & 0xF; ut32 data = (ins >> 4) & 0xFFFF; r_strbuf_setf(&op->buf_asm, "D%d = 0x%x", dreg, data); } // Type 10: Jump (000110B xxxxx COND) else if ((ins >> 19) == 0b00011) { ut32 addr = (ins >> 4) & 0x1FFF; ut32 cond = ins & 0xF; ut8 b = (ins >> 16) & 0x1; const char *db = b ? " (DB)" : ""; if (cond == 0xF) r_strbuf_setf(&op->buf_asm, "JUMP 0x%x%s", addr, db); else r_strbuf_setf(&op->buf_asm, "IF %s JUMP 0x%x%s", COND[cond], addr, db); } // Type 30: NOP (00000000) else if (ins == 0) { r_strbuf_setf(&op->buf_asm, "NOP"); } else { r_strbuf_setf(&op->buf_asm, "unknown (0x%06x)", ins); } return op->size; } RAsmPlugin r_asm_plugin_adsp219x = { .name = "adsp219x", .desc = "Analog Devices ADSP-219x Disassembler (Air-Gapped RE)", .arch = "adsp219x", .bits = 24, .endian = R_SYS_ENDIAN_BIG, .disassemble = &adsp219x_disassemble }; #ifndef R2_PLUGIN_INLINE R_LIB_VERSION_SET(r_asm_plugin_adsp219x, r_asm); #endif