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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user