Files
adsp219x-re/r2plugin/asm_adsp219x.c
Dr. Christian Giessen 6849a701d4 Fix Type 1 AMF bitfield and add real FIR/IIR test ROMs
- Fix Type 1 multifunction: AMF=bits17-13, DD=bits19-18, PD=bits21-20
  (was off by one bit, causing wrong MAC decode on real firmware)
- Add FIR filter ROM (fir.bin): 52 instructions, assembled from AD example
- Add IIR biquad ROM (iir.bin): 28 instructions, assembled from AD example
- Add open21xx-compatible source files (build/fir.dsp, build/iir.dsp)
- Both ROMs disassemble correctly showing expected DSP patterns:
  MAC+dual-read kernels, DO UNTIL loops, ASHIFT scaling, RTS(DB)
- Full regression: isa_test.bin unchanged
2026-04-22 19:47:12 +00:00

659 lines
23 KiB
C

/* asm_adsp219x.c -- Full Radare2 arch plugin for Analog Devices ADSP-219x
Copyright (C) 2026 Dr. Christian Giessen
This file implements the complete ADSP-219x Instruction Set (Types 1-37). */
#include <r_arch.h>
/* --- Tables from Chapter 9 --- */
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", "RES", "RES" };
static const char *reg3[] =
{ "ASTAT", "MSTAT", "SSTAT", "LPSTACKP", "CCODE", "SE", "SB", "PX", "DMPG1", "DMPG2", "IOPG", "IJPG", "RES", "RES", "RES", "STACKP" };
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 *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 *sf_names[] =
{ "LSHIFT (HI)", "LSHIFT (HI, OR)", "LSHIFT (LO)", "LSHIFT (LO, OR)", "ASHIFT (HI)", "ASHIFT (HI, OR)", "ASHIFT (LO)", "ASHIFT (LO, OR)",
"NORM (HI)", "NORM (HI, OR)", "NORM (LO)", "NORM (LO, OR)", "EXP (HI)", "EXP (HIX)", "EXP (LO)", "Derive Block Exponent" };
static const char *xop_alu[] = { "AX0", "AX1", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" };
static const char *xop_mac[] = { "MX0", "MX1", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" };
static const char *xop_shift[] = { "SI", "SR2", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" };
static const char *yop_alu[] = { "AY0", "AY1", "AF", "0" };
static const char *yop_mac[] = { "MY0", "MY1", "SR1", "0" };
/* --- Helpers --- */
static const char *
get_reg (int gp, int idx)
{
switch (gp & 0x3)
{
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 "??";
}
/* --- Decoder --- */
static bool
decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
{
ut32 ins, ins2 = 0;
const ut8 *b = op->bytes;
if (op->size < 3) return false;
ins = ((ut32) b[0] << 16) | ((ut32) b[1] << 8) | (ut32) b[2];
if (op->size >= 6)
ins2 = ((ut32) b[3] << 16) | ((ut32) b[4] << 8) | (ut32) b[5];
op->size = 3;
op->type = R_ANAL_OP_TYPE_UNK;
if (!(mask & R_ARCH_OP_MASK_DISASM)) return true;
/* Priority check: High bits */
ut32 b23_22 = (ins >> 22) & 0x3;
ut32 b21_20 = (ins >> 20) & 0x3;
/* Type 30/31: NOP / IDLE */
if ((ins >> 16) == 0x00)
{
if (ins == 0) { op->mnemonic = strdup ("NOP"); op->type = R_ANAL_OP_TYPE_NOP; }
else if ((ins >> 8) == 0x02) { op->mnemonic = r_str_newf ("IDLE 0x%X", ins & 0xFF); op->type = R_ANAL_OP_TYPE_TRAP; }
return true;
}
/* Type 1: Compute | DM | PM (11xxxx) */
/* PD=bits21-20, DD=bits19-18, AMF=bits17-13, YOP=bits12-11,
XOP=bits10-8, PMI=bits7-6, PMM=bits5-4, DMI=bits3-2, DMM=bits1-0 */
if (b23_22 == 3)
{
ut32 amf = (ins >> 13) & 0x1F;
const char *f = (amf < 16) ? amf_mac[amf] : amf_alu[amf - 16];
int dmi = (ins >> 2) & 3, dmm = ins & 3;
int pmi = (ins >> 6) & 3, pmm = (ins >> 4) & 3;
int dd = (ins >> 18) & 3, pd = (ins >> 20) & 3;
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);
return true;
}
/* Type 3: Direct Memory (10xxxx) */
if (b23_22 == 2)
{
ut32 d = (ins >> 20) & 1, addr = (ins >> 4) & 0xFFFF, reg = ins & 0xF;
if ((ins >> 21) & 1) /* Ireg/Mreg */
op->mnemonic = r_str_newf ("%s(0x%04X) = %s%d", d?"DM":"DM", addr, (reg<8?"I":"M"), reg&7);
else /* Dreg */
op->mnemonic = r_str_newf ("%s(0x%04X) = %s", d?"DM":"DM", addr, reg0[reg]);
return true;
}
/* Type 4: Compute | DM/PM Postmodify (011xxx) */
if ((ins >> 21) == 0x3)
{
ut32 g = (ins >> 20) & 1, amf = (ins >> 13) & 0x1F;
const char *f = (amf < 16) ? amf_mac[amf] : amf_alu[amf-16];
op->mnemonic = r_str_newf ("%s, %s = %cM(I%d += M%d)", f, reg0[(ins>>4)&0xF], g?'P':'D', ((ins>>2)&3)|(g?4:0), (ins&3)|(g?4:0));
return true;
}
/* Type 9/9a: Compute (001000 / 001001) */
/* Bits 23-19 = 00100 */
if ((ins >> 19) == 0x04)
{
ut32 amf = (ins >> 13) & 0x1F;
ut32 xop_i = (ins >> 8) & 0x7;
ut32 yop_i = (ins >> 11) & 0x3;
ut32 cond = ins & 0xF;
const char *f;
const char *dst;
const char *x;
const char *y;
if (amf < 16)
{
f = amf_mac[amf];
dst = "MR";
x = xop_mac[xop_i];
y = yop_mac[yop_i];
}
else
{
f = amf_alu[amf - 16];
dst = "AR";
x = xop_alu[xop_i];
y = yop_alu[yop_i];
}
if (cond == 15)
op->mnemonic = r_str_newf ("%s = %s(%s, %s)",
dst, f, x, y);
else
op->mnemonic = r_str_newf ("IF %s %s = %s(%s, %s)",
cond_str[cond], dst, f, x, y);
return true;
}
/* Type 8: Compute | Dreg1 <- Dreg2 (00101Z) */
/* Bits 23-18 = 001010 (Z=0) or 001011 (Z=1) */
if ((ins >> 18) == 0x0A || (ins >> 18) == 0x0B)
{
ut32 amf = (ins >> 12) & 0x1F;
const char *f = (amf < 16) ? amf_mac[amf] : amf_alu[amf-16];
/* DDREG = bits 8-6 (dest), SDREG = bits 5-0 (src, masked) */
ut32 ddreg = (ins >> 6) & 0x7;
ut32 sdreg = ins & 0x3F;
/* For NONE=ALU case: SDREG = 0x2A (101010) */
if (sdreg == 0x2A)
op->mnemonic = r_str_newf ("NONE = %s", f);
else
op->mnemonic = r_str_newf ("%s, %s = %s", f, xop_alu[ddreg], reg0[sdreg & 0xF]);
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 */
/* 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) */
/* Type 36: Long Jump/Call (2-word, bits 23-16 = 00000101) */
if ((ins >> 16) == 0x05)
{
ut32 s_bit = (ins >> 12) & 1;
ut32 cond = ins & 0xF;
ut32 addr_hi = (ins >> 4) & 0xFF;
ut32 addr_lo = ins2 & 0xFFFFFF;
ut32 addr = (addr_hi << 16) | (addr_lo & 0xFFFF);
op->size = 6;
if (cond == 15)
op->mnemonic = r_str_newf ("%s 0x%06X",
s_bit ? "LCALL" : "LJUMP", addr);
else
op->mnemonic = r_str_newf ("IF %s %s 0x%06X",
cond_str[cond],
s_bit ? "LCALL" : "LJUMP", addr);
op->type = s_bit ? R_ANAL_OP_TYPE_CALL
: R_ANAL_OP_TYPE_JMP;
return true;
}
/* Type 22: DM/PM = Data16 (2-word, bits 23-13 = 00000011110) */
if ((ins >> 13) == 0x1E && !((ins >> 12) & 1))
{
ut32 g = (ins >> 12) & 1;
ut32 ireg = (ins >> 2) & 0x3;
ut32 mreg = ins & 0x3;
ut32 data_lo = (ins >> 4) & 0xFF;
ut32 data_hi = (ins2 >> 16) & 0xFF;
ut32 data = (data_hi << 8) | data_lo;
int base = g ? 4 : 0;
op->size = 6;
op->mnemonic = r_str_newf ("%cM(I%d += M%d) = 0x%04X",
g ? 'P' : 'D', ireg + base, mreg + base, data);
return true;
}
/* Type 22a: PM = Data24 (2-word, bits 23-13 = 00000011111) */
if ((ins >> 13) == 0x1F)
{
ut32 g = (ins >> 12) & 1;
ut32 ireg = (ins >> 2) & 0x3;
ut32 mreg = ins & 0x3;
ut32 data_mid = (ins >> 4) & 0xFF;
ut32 data_hi = (ins2 >> 16) & 0xFF;
ut32 data_lo = (ins2 >> 8) & 0xFF;
ut32 data = (data_hi << 16) | (data_mid << 8) | data_lo;
int base = g ? 4 : 0;
op->size = 6;
op->mnemonic = r_str_newf ("PM(I%d += M%d) = 0x%06X:24",
ireg + base, mreg + base, data);
return true;
}
/* Type 10a: bits 23-18 = 000111 (unconditional 16-bit) */
if ((ins >> 18) == 0x07)
{
/* addr = bits 17-4 (14 bits) | bits 1-0 (2 MSBs) */
ut32 addr = ((ins >> 4) & 0x3FFF) | ((ins & 0x3) << 14);
ut32 b_bit = (ins >> 3) & 1;
ut32 s_bit = (ins >> 2) & 1;
op->mnemonic = r_str_newf ("%s 0x%04X%s",
s_bit ? "CALL" : "JUMP",
addr,
b_bit ? " (DB)" : "");
op->type = s_bit ? R_ANAL_OP_TYPE_CALL
: R_ANAL_OP_TYPE_JMP;
return true;
}
/* Type 10: bits 23-19 = 00011, bit18 = 0 (conditional 13-bit) */
if ((ins >> 19) == 0x03 && !((ins >> 18) & 1))
{
ut32 b_bit = (ins >> 17) & 1;
ut32 addr = (ins >> 4) & 0x1FFF;
ut32 cond = ins & 0xF;
if (cond == 15)
op->mnemonic = r_str_newf ("JUMP 0x%04X%s",
addr,
b_bit ? " (DB)" : "");
else
op->mnemonic = r_str_newf ("IF %s JUMP 0x%04X%s",
cond_str[cond], addr,
b_bit ? " (DB)" : "");
op->type = R_ANAL_OP_TYPE_CJMP;
return true;
}
/* Type 17: Reg = Reg (bits 23-16 = 00001101) */
if ((ins >> 16) == 0x0D)
{
op->mnemonic = r_str_newf ("%s = %s",
get_reg ((ins >> 10) & 3, (ins >> 4) & 0xF),
get_reg ((ins >> 8) & 3, ins & 0xF));
return true;
}
/* Type 20: RTS/RTI (bits 23-16 = 00001010) */
if ((ins >> 16) == 0x0A)
{
ut32 b_bit = (ins >> 15) & 1;
ut32 t_bit = (ins >> 14) & 1;
ut32 cond = (ins >> 4) & 0xF;
const char *ret = t_bit ? "RTI" : "RTS";
if (cond == 15)
op->mnemonic = r_str_newf ("%s%s", ret,
b_bit ? " (DB)" : "");
else
op->mnemonic = r_str_newf ("IF %s %s%s",
cond_str[cond], ret,
b_bit ? " (DB)" : "");
op->type = R_ANAL_OP_TYPE_RET;
return true;
}
/* Type 12: Shift | DM/PM (bits 23-17 = 0001001) */
if ((ins >> 17) == 0x09)
{
ut32 g = (ins >> 16) & 1;
ut32 sf = (ins >> 13) & 0x7;
ut32 d = (ins >> 12) & 1;
ut32 xop_i = (ins >> 9) & 0x7;
ut32 dreg = (ins >> 4) & 0xF;
ut32 ireg = (ins >> 2) & 0x3;
ut32 mreg = ins & 0x3;
int base = g ? 4 : 0;
if (d)
op->mnemonic = r_str_newf ("%s %s, %cM(I%d += M%d) = %s",
sf_names[sf], xop_shift[xop_i],
g ? 'P' : 'D', ireg + base, mreg + base,
reg0[dreg]);
else
op->mnemonic = r_str_newf ("%s %s, %s = %cM(I%d += M%d)",
sf_names[sf], xop_shift[xop_i],
reg0[dreg],
g ? 'P' : 'D', ireg + base, mreg + base);
return true;
}
/* Type 14: Shift | Dreg move (bits 23-16 = 00010100) */
if ((ins >> 16) == 0x14)
{
ut32 sf = (ins >> 12) & 0x7;
ut32 xreg = (ins >> 9) & 0x7;
ut32 ddreg = (ins >> 4) & 0xF;
ut32 sdreg = ins & 0xF;
op->mnemonic = r_str_newf ("%s %s, %s = %s",
sf_names[sf], xop_shift[xreg],
reg0[ddreg], reg0[sdreg]);
return true;
}
/* Type 16: Conditional Shift (bits 23-16 = 00001110) */
if ((ins >> 16) == 0x0E)
{
ut32 sf = (ins >> 12) & 0xF;
ut32 xreg = (ins >> 8) & 0x7;
ut32 cond = ins & 0xF;
if (cond == 15)
op->mnemonic = r_str_newf ("SR = %s %s",
sf_names[sf], xop_shift[xreg]);
else
op->mnemonic = r_str_newf ("IF %s SR = %s %s",
cond_str[cond], sf_names[sf],
xop_shift[xreg]);
return true;
}
/* Type 11: DO UNTIL (bits 23-16 = 00010110) */
if ((ins >> 16) == 0x16)
{
ut32 addr = (ins >> 4) & 0xFFF;
ut32 term = ins & 0xF;
op->mnemonic = r_str_newf ("DO 0x%03X UNTIL %s",
addr, cond_str[term]);
return true;
}
/* Type 15: Shift Imm (bits 23-16 = 00001111) */
if ((ins >> 16) == 0x0F)
{
ut32 sf = (ins >> 12) & 0xF;
ut32 xreg = (ins >> 8) & 0xF;
int8_t exp = (int8_t)(ins & 0xFF);
op->mnemonic = r_str_newf ("SR = %s %s BY %d",
sf_names[sf], reg0[xreg],
exp);
return true;
}
/* Type 18: Mode Control (bits 23-16 = 00001100) */
if ((ins >> 16) == 0x0C)
{
static const char *mbits[] =
{ "INT", "SD", "SR", "BR", "OL", "AS", "MM", "TI" };
char buf[128];
int pos = 0, i;
for (i = 0; i < 8; i++)
{
ut32 v = (ins >> (i * 2)) & 0x3;
if (v == 1)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sDIS %s",
pos ? ", " : "", mbits[i]);
else if (v == 3)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sENA %s",
pos ? ", " : "", mbits[i]);
}
op->mnemonic = pos ? strdup (buf)
: strdup ("MODE NOP");
return true;
}
/* Type 25: SAT MR/SR (bits 23-14 = 0000001100) */
if ((ins >> 14) == 0x0C)
{
ut32 r = (ins >> 13) & 1;
op->mnemonic = r_str_newf ("SAT %s",
r ? "SR" : "MR");
return true;
}
/* Type 33: Reg3 = Data12 (bits 23-16 = 00010000) */
if ((ins >> 16) == 0x10)
{
ut32 data = (ins >> 4) & 0xFFF;
ut32 reg = ins & 0xF;
op->mnemonic = r_str_newf ("%s = 0x%03X",
reg3[reg], data);
return true;
}
/* Type 19: Indirect Jump/Call (bits 23-16 = 00001011) */
if ((ins >> 16) == 0x0B)
{
ut32 b_bit = (ins >> 15) & 1;
ut32 s_bit = (ins >> 14) & 1;
ut32 g = (ins >> 13) & 1;
ut32 cond = (ins >> 4) & 0xF;
ut32 ireg = ins & 0x3;
int base = g ? 4 : 0;
if (cond == 15)
op->mnemonic = r_str_newf ("%s (I%d)%s",
s_bit ? "CALL" : "JUMP",
ireg + base,
b_bit ? " (DB)" : "");
else
op->mnemonic = r_str_newf ("IF %s %s (I%d)%s",
cond_str[cond],
s_bit ? "CALL" : "JUMP",
ireg + base,
b_bit ? " (DB)" : "");
op->type = s_bit ? R_ANAL_OP_TYPE_CALL
: R_ANAL_OP_TYPE_JMP;
return true;
}
/* Type 21: MODIFY (bits 23-16 = 00000001, bit15=1) */
if ((ins >> 16) == 0x01 && ((ins >> 15) & 1))
{
ut32 g = (ins >> 12) & 1;
ut32 ireg = ins & 0x3;
ut32 mreg = (ins >> 2) & 0x3;
int base = g ? 4 : 0;
op->mnemonic = r_str_newf ("MODIFY(I%d += M%d)",
ireg + base, mreg + base);
return true;
}
/* Type 23: DIVQ (bits 23-12 = 000000111101) */
if ((ins >> 12) == 0x03D)
{
ut32 xop_i = (ins >> 8) & 0x7;
op->mnemonic = r_str_newf ("DIVQ %s",
xop_alu[xop_i]);
return true;
}
/* Type 24: DIVS (bits 23-13 = 00000011100) */
if ((ins >> 13) == 0x1C)
{
ut32 yop_i = (ins >> 11) & 0x3;
ut32 xop_i = (ins >> 8) & 0x7;
op->mnemonic = r_str_newf ("DIVS %s, %s",
yop_alu[yop_i],
xop_alu[xop_i]);
return true;
}
/* Type 26: Push/Pop/Cache (bits 23-16 = 00001000) */
if ((ins >> 16) == 0x08)
{
ut32 cf = (ins >> 7) & 1;
ut32 ppp = (ins >> 4) & 0x7;
ut32 lpp = (ins >> 2) & 0x3;
ut32 spp = ins & 0x3;
char buf[64];
int pos = 0;
if (cf)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "FLUSH CACHE");
if (ppp == 1)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sPUSH PC",
pos ? ", " : "");
else if (ppp == 2)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sPOP PC",
pos ? ", " : "");
if (lpp == 1)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sPUSH LOOP",
pos ? ", " : "");
else if (lpp == 2)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sPOP LOOP",
pos ? ", " : "");
if (spp == 1)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sPUSH STS",
pos ? ", " : "");
else if (spp == 2)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sPOP STS",
pos ? ", " : "");
op->mnemonic = pos ? strdup (buf)
: strdup ("STACK NOP");
return true;
}
/* Type 29: Dreg <-> DM imm modify (bits 23-18 = 000010) */
if ((ins >> 18) == 0x02)
{
ut32 u = (ins >> 16) & 1;
ut32 dru = (ins >> 14) & 0x3;
ut32 g = (ins >> 13) & 1;
ut32 d = (ins >> 12) & 1;
ut32 mod = (ins >> 4) & 0xFF;
ut32 ireg = (ins >> 2) & 0x3;
ut32 drl = ins & 0x3;
ut32 dreg = (dru << 2) | drl;
int8_t smod = (int8_t) mod;
int base = g ? 4 : 0;
const char *mem = g ? "PM" : "DM";
const char *op_str = u ? "+=" : "+";
if (d)
op->mnemonic = r_str_newf ("%s(I%d %s %d) = %s",
mem, ireg + base, op_str, smod,
reg0[dreg]);
else
op->mnemonic = r_str_newf ("%s = %s(I%d %s %d)",
reg0[dreg], mem, ireg + base, op_str,
smod);
return true;
}
/* Type 32: Any Reg <-> DM/PM (bits 23-17 = 0001010, bit11=0) */
if ((ins >> 17) == 0x0A && !((ins >> 11) & 1))
{
ut32 ms = (ins >> 15) & 1;
ut32 u_bit = (ins >> 14) & 1;
ut32 g = (ins >> 13) & 1;
ut32 d = (ins >> 12) & 1;
ut32 rgp = (ins >> 8) & 0x3;
ut32 reg = (ins >> 4) & 0xF;
ut32 ireg = (ins >> 2) & 0x3;
ut32 mreg = ins & 0x3;
int base = g ? 4 : 0;
const char *mem = (ms || g) ? "PM" : "DM";
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);
else
op->mnemonic = r_str_newf ("%s = %s(I%d %s M%d)",
rname, mem, ireg + base, mod,
mreg + base);
return true;
}
/* Type 32a: DAG reg store + transfer (bits 23-17=0001010, bit11=1) */
if ((ins >> 17) == 0x0A && ((ins >> 11) & 1))
{
ut32 u_bit = (ins >> 14) & 1;
ut32 g = (ins >> 13) & 1;
ut32 rgp = (ins >> 8) & 0x3;
ut32 dag_reg = (ins >> 4) & 0x7;
ut32 ireg = (ins >> 2) & 0x3;
ut32 mreg = ins & 0x3;
int base = g ? 4 : 0;
const char *mod = u_bit ? "+=" : "+";
const char *rname = get_reg (rgp, dag_reg);
op->mnemonic = r_str_newf (
"DM(I%d %s M%d) = %s, %s = I%d",
ireg + base, mod, mreg + base,
rname, rname, ireg + base);
return true;
}
/* Type 21a: MODIFY imm (bits 23-16 = 00000001, bit15=0) */
if ((ins >> 16) == 0x01 && !((ins >> 15) & 1))
{
ut32 g = (ins >> 12) & 1;
ut32 ireg = ins & 0x3;
int8_t mod = (int8_t)((ins >> 4) & 0xFF);
int base = g ? 4 : 0;
op->mnemonic = r_str_newf ("MODIFY(I%d += %d)",
ireg + base, mod);
return true;
}
/* Type 34: IO reg (bits 23-16 = 00000110, bit15=1) */
if ((ins >> 16) == 0x06 && ((ins >> 15) & 1))
{
ut32 d = (ins >> 12) & 1;
ut32 addr_hi = (ins >> 13) & 0x3;
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]);
else
op->mnemonic = r_str_newf ("%s = IO(0x%03X)",
reg0[dreg], addr);
return true;
}
/* Type 35: Sys ctrl reg (bits 23-16 = 00000110, bit15=0) */
if ((ins >> 16) == 0x06 && !((ins >> 15) & 1))
{
ut32 d = (ins >> 12) & 1;
ut32 addr = (ins >> 4) & 0xFF;
ut32 dreg = ins & 0xF;
if (d)
op->mnemonic = r_str_newf ("REG(0x%02X) = %s",
addr, reg0[dreg]);
else
op->mnemonic = r_str_newf ("%s = REG(0x%02X)",
reg0[dreg], addr);
return true;
}
/* Type 37: SETINT/CLRINT (bits 23-15 = 000001110) */
if ((ins >> 15) == 0x0E)
{
ut32 c = (ins >> 5) & 1;
ut32 bit = ins & 0xF;
op->mnemonic = r_str_newf ("%s %d",
c ? "CLRINT" : "SETINT", bit);
return true;
}
}
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_MINOP_SIZE: case R_ARCH_INFO_MAXOP_SIZE: return 3;
default: return -1;
}
}
const RArchPlugin r_arch_plugin_adsp219x = {
.meta = { .name = "adsp219x", .author = "Dr. Christian Giessen", .desc = "ADSP-219x Master Plugin", .license = "LGPL-3.0-only" },
.arch = "adsp219x", .bits = R_SYS_BITS_PACK(24), .endian = R_SYS_ENDIAN_BIG, .info = archinfo, .decode = (RArchPluginDecodeCallback)decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = { .type = R_LIB_TYPE_ARCH, .data = (void *)&r_arch_plugin_adsp219x, .version = R2_VERSION };
#endif