Description
While investigating #892 to make the promotion of JMP/JSR optional rather than mandatory, and no longer the default, I discovered it's incapable of treating a proc marked far as a request to promote JMP/JSR to that proc to far calls. Instead, only a far import, or a far segment will be able to make the instruction promote.
However, it does produce a range error at the end of assembly, so it's not a severe bug. The range error might be a little hard to understand, but at least it's not producing invalid code. In this case, the user can manually promote them with an f: prefix or using JML/JSL to correct the error.
However, it seems inappropriate that declaring a proc as far is insufficient here? I find it a confusing exception.
.p816
.proc fp : far
rtl
.endproc
jmp fp ; Error: Range error (Address size 3 does not match fragment size 2)
jsr fp ; Error: Range error (Address size 3 does not match fragment size 2)
My incomplete assessement of what's happening. First when generating the instruction:
- EvalEA > StudyExpr > StudySymbol gets a far address size from GetSymAddrSize.
- When it returns to StudyExpr the last half checks if the ExprDesc is valid and then proceeds to throw away the symbol's address size and build a new one.
- During this last step, SymCount is 0 but SecCount is 1. This causes it to derive the new size from the one SecRef to the enclosing segment (which is by default a "near" segment).
- EmitCode generates a near expression.
At the end of assembly:
- During SegDone it does a new StudyExpr on the fragment.
- StudyExpr descends into StudyNearAddr rather than StudySymbol.
- StudyNearAddr > StudyExprInternal > StudySymbol which again finds a far address for the symbol.
- StudyNearAddr then calls ED_IsConst, which determines it is not const because it has a SecRef.
- StudyNearAddr invalidates the ExprDesc because it is not const. Flags it as ED_TOO_COMPLEX.
- StudyExpr this time has an invalid ExprDesc so it doesn't throw away and rebuild the address size.
- SegDone does a range check because it's not const, and finds 3 > 2. Error is generated.
So, if there's a fix, I guess it's to pay attention to the far proc request during the re-build phase of StudyExpr? I'm not sure exactly how this could be determined. The symbol gets the far address size assigned in DoProc, but I'm not sure how StudyExpr should be made aware of it and incorporate the information in the address size re-build step. Wondering what SymCount means, and whether it should be > 0?
The complexity of the expression evaluation code makes me hesitate here. I'd be worried an attempt to "fix" this might de-optimize other expression simplifications that are important.
Anyway, because this is at caught as an error, and also because as per #892 I think this behaviour is a bad default anyway, this is probably a very low priority bug. Maybe not worth trying to fix.
The main problem here is that "proc : far" seems to be a half-measure that doesn't do everything we expect. It seems like it should be able to assist JMP/JSR promotion, but it apparently can't.