w6a: bare negative constant parses honestly; name(reg) rejects

Two parse.c operand defects. A bare `-8` (no $) double-negated to
+8: a_parsenum lets strtoll consume the sign, and the caller's
`off * sign` re-applied it (the D_INDIR arm never multiplied, which
is why -8(BP) always worked); the wwstage twin was already correct,
so this was a latent cs!=ww on hand-written source. The name(REG)
non-SB arm faked a D_INDIR off an UNCHECKED reg_lookup and silently
discarded the parsed ident and +disp -- both stages; the shape has
no encoding and now rejects loud.
This commit is contained in:
2026-08-09 01:12:41 +09:00
parent 5006bf4fb9
commit 4a5f64fc3d
2 changed files with 17 additions and 11 deletions

View File

@@ -197,8 +197,11 @@ parse_operand(Asm *a, const char *s, Aoperand *out)
out->offset = off;
return 0;
}
/* a_parsenum consumed the sign itself (strtoll); the local
* `sign` exists only so isdigit() sees past the '-'.
* Multiplying re-applied it: bare `-8` parsed as +8. */
out->type = D_CONST;
out->offset = off * sign;
out->offset = off;
return 0;
}
@@ -233,11 +236,12 @@ parse_operand(Asm *a, const char *s, Aoperand *out)
out->offset = sym_disp;
return 0;
}
out->type = D_INDIR;
out->reg = r;
out->offset = 0;
/* unusual case: name(REG) with named offset; not used */
return 0;
/* name(REG) with a non-SB register has no encoding
* here; the old arm faked D_INDIR off an UNCHECKED
* reg_lookup and silently discarded the ident and
* +disp (rule 7). */
err(a, "unsupported name(reg) operand");
return -1;
}
int r = reg_lookup(buf);