Rewrite Type 9/9a decode: five sub-encodings

Type 9a (register-file, unconditional):
  - XREG=bits11-8 (4 bits), YREG=bits3-0 (4 bits), both reg0[]
  - Discriminated by bits5-4 = 10
  - Verified: ar=mx0 xor my0, mr=ax0*ay0(ss)

Type 9 standard (conditional):
  - XOP=bits10-8, YOP=bits12-11, COND=bits3-0
  - bits7-4 = 0000 required
  - Verified: all ALU ops, conditional MAC

Type 9 YOP=0:
  - bits12-11 = 11, bits7-4 = 0000
  - Renders f(xop, 0)

Type 9 MAC squaring:
  - bits12-11 = 00, bit4 = 1, bits7-5 = 000
  - Renders f(xop^2)

Type 9 constant YOP:
  - CC=bits7-6, BO=bits5-4
  - Renders f(xop, const)

Tested with open21xx assembler output for 15 instructions.
Full regression: isa_test, fir, iir unchanged.
This commit is contained in:
Dr. Christian Giessen
2026-04-22 20:01:08 +00:00
parent dbcf04eb62
commit 1c28f027b8
3 changed files with 97 additions and 14 deletions

View File

@@ -0,0 +1,30 @@
/*
* type9_test.dsp -- Test all Type 9/9a sub-encodings.
*/
.section/PM program0;
.global _start;
_start:
/* Type 9 standard: conditional ALU */
ar = ax0 + ay0;
if ne ar = ax0 - ay0;
ar = ax0 and ay0;
ar = pass ax0;
ar = -ax0;
ar = abs ax0;
/* Type 9 standard: conditional MAC */
mr = mx0 * my0 (ss);
if eq mr = mr + mx0 * my0 (ss);
mr = mr - mx0 * my0 (ss);
mr = 0;
/* Type 9a: unconditional register-file ALU */
ar = ax0 + ay1;
ar = mx0 xor my0;
/* Type 9a: unconditional register-file MAC */
mr = ax0 * ay0 (ss);
nop;
_halt:
jump _halt;

View File

@@ -142,39 +142,92 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
return true;
}
/* Type 9/9a: Compute (001000 / 001001) */
/* Bits 23-19 = 00100 */
/* Type 9/9a: Compute (bits 23-19 = 00100)
Z=bit18, AMF=bits17-13.
Five sub-encodings distinguished by lower bits:
9a register-file: bits5-4 = 10
9 standard: bits7-4 = 0000, bits12-11 != 11
9 YOP=0: bits7-4 = 0000, bits12-11 = 11
9 MAC square: bits12-11 = 00, bit4 = 1, bits7-5 = 000
9 constant YOP: otherwise */
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;
/* Select AMF mnemonic and XOP table based on operation */
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 9a: register-file form (bits5-4 = 10)
XREG=bits11-8 (4 bits), YREG=bits3-0 (4 bits),
both index into reg0[]. */
if (((ins >> 4) & 0x3) == 0x2)
{
ut32 xreg = (ins >> 8) & 0xF;
ut32 yreg = ins & 0xF;
op->mnemonic = r_str_newf ("%s = %s(%s, %s)",
dst, f, reg0[xreg],
reg0[yreg]);
return true;
}
ut32 cond = ins & 0xF;
ut32 yop_i = (ins >> 11) & 0x3;
const char *cp = (cond == 15) ? "" : "IF ";
const char *cs = (cond == 15) ? "" : cond_str[cond];
const char *sp = (cond == 15) ? "" : " ";
/* MAC squaring: bits12-11 = 00, bit4 = 1, bits7-5 = 000 */
if (yop_i == 0 && ((ins >> 4) & 0xF) == 0x1)
{
op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s^2)",
cp, cs, sp, dst, f, x);
return true;
}
/* YOP=0 form: bits12-11 = 11, bits7-4 = 0000 */
if (yop_i == 3 && ((ins >> 4) & 0xF) == 0)
{
op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s, 0)",
cp, cs, sp, dst, f, x);
return true;
}
/* Standard form: bits7-4 = 0000 */
if (((ins >> 4) & 0xF) == 0)
{
const char *y = (amf < 16) ? yop_mac[yop_i]
: yop_alu[yop_i];
op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s, %s)",
cp, cs, sp, dst, f, x, y);
return true;
}
/* Constant YOP form: CC=bits7-6, BO=bits5-4 */
{
ut32 cc = (ins >> 6) & 0x3;
ut32 bo = (ins >> 4) & 0x3;
int val = (int) cc;
if (bo & 0x2)
val = -val;
op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s, %d)",
cp, cs, sp, dst, f, x, val);
return true;
}
}
/* Type 8: Compute | Dreg1 <- Dreg2 (00101Z)

Binary file not shown.