Range checking for 65816 mode when abs addresses are assumed rather than known #885
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
This is a possible resolution to issue: #879
It looks like a satisfactory resolution to me, but I could use code review and/or assistance in testing before I would be confident that this should be merged.
.
What I found was that when the address size of an operand was not sufficiently known in 65816 mode, it would use
GenWordExprwhich creates anEXPR_WORD0type expression that automatically truncates to 16-bit. Otherwise if it is known at that line, the assembler will just generate an instruction of known size.See:
cc65/src/ca65/instr.c
Line 1220 in 392e6e1
I believe the idea is that by truncating it, the address was prepared in advance for the linker, which in 65816 correctly has to truncate near addresses to remove their bank byte. However, this disabled the ability to check if this was a valid truncation.
My replacement creates a new expression type
EXPR_NEARADDR, which the linker will treat the same asEXPR_WORD0as a 16-bit truncation, but now the assembler can range check it inSegDone(unless the relaxed checking mode is used).This change seems to correctly catch the error of accidentally making a reference to a symbol from a
farsegment before that segment is declared. If the instruction was assumed near, but the symbol was later declared far, this now gets caught duringSegDone.One caveat: a later (or prior) export via
.global+: fardoes not override the address modifier of the symbol's containing segment. I think this is correct behaviour, so that near addresses used within the file can be exported globally, but the consequence might be unintuitive: a.global : farwill cause a symbol to assume far addressing until its containing segment is reached, which overrides it. (This feels correct to me, but still weird to think through.).
Also, was it appropriate to add the EXPR_NEARADDR enum in the middle of the list, or should it have been appended to the end? (Would that invalidate existing object files?)
The text was updated successfully, but these errors were encountered: