New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
65816 JSR and JMP fail to produce error for truncated range #879
Comments
|
As another aside, I can't think of a way to forward-declare a label as :far aside from .global, but that has the side effect of making it an exported symbol. Is there any way to do that without? |
|
If I get this right then I'd say that not issuing at least a warning has to be considered as a bug. |
|
I think it should be an error. I can't really think of a use for the 16-bit truncation, but .loword could easily be used to suppress the error if that's what someone really wanted? . There is a related truncation to 16-bits that happens with data instructions as well i.e. you can use a label with LDA and then later in the file define that label in a :far segment, and the linker won't give any indication that the earlier use was truncated. It's sort of like how 6502 silently produces abs addressing for zp references if you forget to declare them ahead of time, but in this case produces broken code because it's truncating rather than expanding. I had initially not thought of this as the same bug, because 65816 programmers have to manage the DB register anyway, but on further reflection I believe if something is declared as :far it indicates that they wanted it to be using 24-bit address, so it seems like this too should be an error? I think the behaviour of assuming abs by default is good. Far references should be rare, normally, and with a link time error to point them out it'd be easy to add the needed |
A JSR or JMP from one bank to another can only work if it gets promoted to a JSL/JML. If the assembler failed to produce a 3-byte operand, the linker should throw an error when it's trying to fill in those values with a truncated 2-byte operand, unless both source and destination bank are the same.
In its current form, JSR and JMP are very prone to errors of this nature. It's very easy to forget that a label is a far target and accidentally use JSR instead of JSL. If you do this, you get non-functional code generated with no warning or error.
The ability of JSR /JMP to promote to JSL/JML increases the possibility of confusion here, especially with the way this assembler works in one pass, it's very easy to fail to annotate a segment with :far or declare it below rather than above in the file. Generating a range error when the linker later discovers it needed a 3-byte operand would be a lot better than just quietly generating a JSR that will never work.
A simple code example demonstrating the problem:
65816_jsr_range_fail.zip
In this example we have two impossible JSR instructions that will generate invalid code with no error.
As an aside I would ask if there's a way to turn off promotion of JSR/JMP to JSL/JML as well? It doesn't affect the error directly, but requiring it to be explicit as a habit would give the programmer a visual reminder that a label is far and will require an RTL. Positive reinforcement for remembering the type of procedure by not allowing its calls to "hide" as a JSR. (Though I would probably suggest that this is an appropriate promotion in .smart mode, but not with .smart off? Currently it just does it always.)
The text was updated successfully, but these errors were encountered: