Implement Types 8, 9, 10a, 11, 15, 17, 18, 19, 20, 21, 23, 24, 25, 26, 33, 37

- Type 8: Compute + Dreg move
- Type 9/9a: Standalone ALU/MAC compute (conditional/unconditional)
- Type 10a: Unconditional 16-bit jump/call (fixed bitfield decode)
- Type 10: Conditional 13-bit jump (fixed COND field)
- Type 18: Mode control (ENA/DIS AS, MM, BR, etc.)
- Type 19: Indirect jump/call via Ireg
- Type 20: RTS/RTI with correct COND extraction (fixed bug)
- Type 21: MODIFY(Ireg += Mreg)
- Type 23: DIVQ
- Type 24: DIVS
- Type 25: SAT MR/SR
- Type 26: Push/Pop/Flush Cache
- Type 33: Reg3 = Data12 (short constant load)
- Type 37: SETINT/CLRINT
- Type 15: Sign-extended shift exponent
This commit is contained in:
Dr. Christian Giessen
2026-04-22 19:34:01 +00:00
parent d08d32203f
commit 62b9363c13
2 changed files with 264 additions and 9 deletions

View File

@@ -109,7 +109,42 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
{
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));
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;
}
@@ -117,7 +152,6 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
/* Bits 23-18 = 001010 (Z=0) or 001011 (Z=1) */
if ((ins >> 18) == 0x0A || (ins >> 18) == 0x0B)
{
ut32 z = (ins >> 18) & 1;
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) */
@@ -144,16 +178,237 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
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 ((ins >> 19) == 0x3) /* Type 10/10a Jumps */
/* Type 10a: bits 23-18 = 000111 (unconditional 16-bit) */
if ((ins >> 18) == 0x07)
{
ut32 db = (ins >> 18) & 1, s = (ins >> 17) & 1, cond = ins & 0xF;
op->mnemonic = r_str_newf ("%s%s %s 0x%X%s", (cond==15?"":"IF "), (cond==15?"":cond_str[cond]), s?"CALL":"JUMP", (ins>>4)&0x1FFF, db?" (DB)":"");
/* 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 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 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;
}
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 17 */
if ((ins >> 16) == 0x0A) { op->mnemonic = r_str_newf ("%s%s %s", (ins&0xF)==15?"":cond_str[ins&0xF], (ins&0xF)==15?"":" ", (ins>>13)&1?"RTI":"RTS"); return true; } /* Type 20 */
if ((ins >> 16) == 0x16) { op->mnemonic = r_str_newf ("DO 0x%X UNTIL %s", (ins>>4)&0xFFF, cond_str[ins&0xF]); return true; } /* Type 11 */
if ((ins >> 16) == 0x0F) { op->mnemonic = r_str_newf ("SR = %s %s BY 0x%X", sf_names[(ins>>12)&0xF], reg0[(ins>>8)&0xF], ins&0xFF); return true; } /* Type 15 */
}
op->mnemonic = r_str_newf ("unk 0x%06X", ins);