diff --git a/cmd/w6a/parse.c b/cmd/w6a/parse.c index cd254d93..9feef271 100644 --- a/cmd/w6a/parse.c +++ b/cmd/w6a/parse.c @@ -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); diff --git a/selfhost/cmd/w6a/parse.ww b/selfhost/cmd/w6a/parse.ww index 1aff73df..41caf4cd 100644 --- a/selfhost/cmd/w6a/parse.ww +++ b/selfhost/cmd/w6a/parse.ww @@ -338,12 +338,14 @@ fn parseoperand(a: *asm_, p: *u8, offin: u64, n: u64, out: *aoperand) u64 = { out.atype = D_EXTERN; out.asym = dupstr(p + istart, in_); out.offset = symdisp; - } else { - out.atype = D_INDIR; - out.reg = r; - out.offset = 0i64; + return cur2 + 1u64; }; - return cur2 + 1u64; + // name(REG) with a non-SB register has no + // encoding here; the old arm faked D_INDIR + // off an UNCHECKED reglookup and silently + // discarded the ident and +disp (rule 7). + perr(a, "unsupported name(reg) operand"); + return n; }; perr(a, "missing ')'"); return n;