Fix Constant-YOP table, Type 18, truncation guards

Type 9 Constant-YOP: Implement exact constant table from docs.
  Index = (YY<<2)|CC, value = 1<<idx for BO=01, -(1<<idx)-1
  for BO=11.  Special case idx=15: -32768 / +32767.
  (was: simple cc with optional negate, completely wrong values)

Type 18: Fix DIS encoding to check for bit pattern 10 (was 01).
  Verified all 8 modes against assembler: ENA/DIS for
  AS, MM, BR, TI all correct.

Truncation guards: Use saved 'avail' from original op->size
  instead of checking op->size after it was set to 3.
  (was: always true, guards never triggered)
This commit is contained in:
Dr. Christian Giessen
2026-04-22 20:05:17 +00:00
parent 1c28f027b8
commit ae98262bb7
3 changed files with 37 additions and 10 deletions

View File

@@ -61,10 +61,11 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
{
ut32 ins, ins2 = 0;
const ut8 *b = op->bytes;
if (op->size < 3) return false;
int avail = op->size;
if (avail < 3) return false;
ins = ((ut32) b[0] << 16) | ((ut32) b[1] << 8) | (ut32) b[2];
if (op->size >= 6)
if (avail >= 6)
ins2 = ((ut32) b[3] << 16) | ((ut32) b[4] << 8) | (ut32) b[5];
op->size = 3;
op->type = R_ANAL_OP_TYPE_UNK;
@@ -217,13 +218,22 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
return true;
}
/* Constant YOP form: CC=bits7-6, BO=bits5-4 */
/* Constant YOP form: YY=bits12-11, CC=bits7-6, BO=bits5-4.
Index = (YY<<2)|CC. BO=01: val = 1<<idx (idx<15)
or -32768 (idx=15). BO=11: val = -(1<<idx)-1
or +32767 (idx=15). */
{
ut32 yy = (ins >> 11) & 0x3;
ut32 cc = (ins >> 6) & 0x3;
ut32 bo = (ins >> 4) & 0x3;
int val = (int) cc;
if (bo & 0x2)
val = -val;
ut32 idx = (yy << 2) | cc;
int32_t val;
if (idx == 15)
val = (bo & 0x2) ? 32767 : -32768;
else if (bo & 0x2)
val = -((int32_t)(1 << idx)) - 1;
else
val = (int32_t)(1 << idx);
op->mnemonic = r_str_newf ("%s%s%s%s = %s(%s, %d)",
cp, cs, sp, dst, f, x, val);
return true;
@@ -285,7 +295,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
/* Type 36: Long Jump/Call (2-word, bits 23-16 = 00000101) */
if ((ins >> 16) == 0x05)
{
if (op->size < 6)
if (avail < 6)
{
op->mnemonic = r_str_newf ("trunc L%s 0x%06X",
((ins >> 12) & 1) ? "CALL" : "JUMP", ins);
@@ -314,7 +324,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
/* Type 22: DM/PM = Data16 (2-word, bits 23-13 = 00000011110) */
if ((ins >> 13) == 0x1E && !((ins >> 12) & 1))
{
if (op->size < 6)
if (avail < 6)
{
op->mnemonic = r_str_newf ("trunc DM_IMM16 0x%06X",
ins);
@@ -336,7 +346,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
/* Type 22a: PM = Data24 (2-word, bits 23-13 = 00000011111) */
if ((ins >> 13) == 0x1F)
{
if (op->size < 6)
if (avail < 6)
{
op->mnemonic = r_str_newf ("trunc PM_IMM24 0x%06X",
ins);
@@ -512,7 +522,7 @@ decode (RArchSession *as, RAnalOp *op, RAnalOpMask mask)
for (i = 0; i < 8; i++)
{
ut32 v = (ins >> (i * 2)) & 0x3;
if (v == 1)
if (v == 2)
pos += snprintf (buf + pos,
sizeof (buf) - pos, "%sDIS %s",
pos ? ", " : "", mbits[i]);

Binary file not shown.