Merge pull request #2001 from bbbradsmith/ca65_long_jsr_jmp_rts

ca65 jsr/jmp/rts will not promote to jsl/jml/rtl by default, new feature long_jsr_jmp_rts to re-enable this ability
This commit is contained in:
Bob Andrews 2023-02-24 19:34:37 +01:00 committed by GitHub
commit 302d6ee4a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 94 additions and 11 deletions

View File

@ -184,7 +184,7 @@ Here is a description of all the command line options:
Enable an emulation feature. This is identical as using <tt/.FEATURE/
in the source with two exceptions: Feature names must be lower case, and
each feature must be specified by using an extra <tt/--feature/ option,
each feature must be specified by using a separate <tt/--feature/ option,
comma separated lists are not allowed.
See the discussion of the <tt><ref id=".FEATURE" name=".FEATURE"></tt>
@ -2833,6 +2833,23 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH
overridden. When using this feature, you may also get into trouble if
later versions of the assembler define new keywords starting with a dot.
<tag><tt>long_jsr_jmp_rts</tt><label id="long_jsr_jmp_rts"></tag>
Affects 65816 mode only.
Allows <tt>jsr</tt> and <tt>jmp</tt> to produce long jumps if the target
address has been previously declared in a <tt>far</tt> segment,
or imported as <tt>far</tt>.
Otherwise <tt>jsl</tt> and <tt>jml</tt> must be used instead.
Also allows <tt><ref id=".SMART" name=".SMART"></tt> to convert <tt>rts</tt>
to a long return <tt>rtl</tt> when the enclosing scope or memory model
indicates returning from a <tt>far</tt> procedure.
This permits compatibility with the old behavior of this assembler, or other
assemblers which similarly allowed <tt>jsr</tt> and <tt>jmp</tt> to be used
this way.
<tag><tt>loose_char_term</tt><label id="loose_char_term"></tag>
Accept single quotes as well as double quotes as terminators for char
@ -4002,7 +4019,9 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
the assembler cannot trace the execution flow this may lead to false
results in some cases. If in doubt, use the <tt/.Inn/ and <tt/.Ann/
instructions to tell the assembler about the current settings.
<item>In 65816 mode, replace a <tt/RTS/ instruction by <tt/RTL/ if it is
<item>In 65816 mode, if the <tt><ref id="long_jsr_jmp_rts"
name="long_jsr_jmp_rts"></tt> feature is enabled,
smart mode will replace a <tt/RTS/ instruction by <tt/RTL/ if it is
used within a procedure declared as <tt/far/, or if the procedure has
no explicit address specification, but it is <tt/far/ because of the
memory model used.

View File

@ -66,6 +66,7 @@ static const char* const FeatureKeys[FEAT_COUNT] = {
"addrsize",
"bracket_as_indirect",
"string_escapes",
"long_jsr_jmp_rts",
};
@ -125,6 +126,7 @@ feature_t SetFeature (const StrBuf* Key)
case FEAT_ADDRSIZE: AddrSize = 1; break;
case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break;
case FEAT_STRING_ESCAPES: StringEscapes = 1; break;
case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = 1; break;
default: /* Keep gcc silent */ break;
}

View File

@ -68,6 +68,7 @@ typedef enum {
FEAT_ADDRSIZE,
FEAT_BRACKET_AS_INDIRECT,
FEAT_STRING_ESCAPES,
FEAT_LONG_JSR_JMP_RTS,
/* Special value: Number of features available */
FEAT_COUNT

View File

@ -67,6 +67,7 @@ unsigned char LineCont = 0; /* Allow line continuation */
unsigned char LargeAlignment = 0; /* Don't warn about large alignments */
unsigned char RelaxChecks = 0; /* Relax a few assembler checks */
unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */
unsigned char LongJsrJmpRts = 0; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
unsigned char WarningsAsErrors = 0; /* Error if any warnings */
/* Emulation features */

View File

@ -69,6 +69,7 @@ extern unsigned char LineCont; /* Allow line continuation */
extern unsigned char LargeAlignment; /* Don't warn about large alignments */
extern unsigned char RelaxChecks; /* Relax a few assembler checks */
extern unsigned char StringEscapes; /* Allow C-style escapes in strings */
extern unsigned char LongJsrJmpRts; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
extern unsigned char WarningsAsErrors; /* Error if any warnings */
/* Emulation features */

View File

@ -120,9 +120,21 @@ static void PutJMP (const InsDesc* Ins);
** to check for this case and is otherwise identical to PutAll.
*/
static void PutJMP816 (const InsDesc* Ins);
/* Handle the JMP instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JMP.
** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC,
** because the [] notation for long indirection makes the generated instruction unambiguous.
*/
static void PutJSR816 (const InsDesc* Ins);
/* Handle the JSR instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JSR.
*/
static void PutRTS (const InsDesc* Ins attribute ((unused)));
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
** the enclosing scope is FAR.
** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies.
*/
static void PutAll (const InsDesc* Ins);
@ -758,9 +770,9 @@ static const struct {
{ "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll },
{ "JML", 0x4000010, 0x5c, 1, PutAll },
{ "JMP", 0x4010818, 0x4c, 6, PutAll },
{ "JMP", 0x4010818, 0x4c, 6, PutJMP816 },
{ "JSL", 0x0000010, 0x20, 7, PutAll },
{ "JSR", 0x0010018, 0x20, 7, PutAll },
{ "JSR", 0x0010018, 0x20, 7, PutJSR816 },
{ "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
{ "LDX", 0x0c0030c, 0xa2, 1, PutAll },
{ "LDY", 0x0c0006c, 0xa0, 1, PutAll },
@ -1627,12 +1639,46 @@ static void PutJMP (const InsDesc* Ins)
static void PutRTS (const InsDesc* Ins attribute ((unused)))
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
** the enclosing scope is FAR.
static void PutJMP816 (const InsDesc* Ins)
/* Handle the JMP instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JMP.
** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC,
** because the [] notation for long indirection makes the generated instruction unambiguous.
*/
{
if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
if (LongJsrJmpRts) {
PutJMP (Ins);
} else {
InsDesc InsAbs = *Ins;
InsAbs.AddrMode &= ~(AM65_ABS_LONG);
PutJMP (&InsAbs);
}
}
static void PutJSR816 (const InsDesc* Ins)
/* Handle the JSR instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JSR.
*/
{
if (LongJsrJmpRts) {
PutAll (Ins);
} else {
InsDesc InsAbs = *Ins;
InsAbs.AddrMode &= ~(AM65_ABS_LONG);
PutJMP (&InsAbs);
}
}
static void PutRTS (const InsDesc* Ins attribute ((unused)))
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies.
*/
{
if (LongJsrJmpRts && SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
Emit0 (0x6B); /* RTL */
} else {
Emit0 (0x60); /* RTS */

View File

@ -3,5 +3,5 @@ GLOBAL {
};
RANGE { START $8000; END $8229; ADDRMODE "MX"; TYPE Code;};
RANGE { START $822a; END $824b; ADDRMODE "mx"; TYPE Code;};
RANGE { START $822a; END $825b; ADDRMODE "mx"; TYPE Code;};

View File

@ -151,10 +151,11 @@ BVC LABEL
BVS LABEL
BRL LABEL
JMP $1234
JMP $FEDCBA
JML $FEDCBA
JMP ($1234)
JMP ($1234,X)
JMP [$1234]
JML [$1234] ; alternative to JMP []
JSL $123456
JSR $1234
JSR ($1234,X)
@ -271,3 +272,15 @@ BIT #$5432
LDA #$5432
LDX #$5432
LDY #$5432
; test of smart and long_jsr_jmp_rts
.smart
.proc short_rts : far
RTS ; not promoted to RTL
.endproc
.feature long_jsr_jmp_rts
JSR $FEDCBA ; promoted to JSL
JMP $FEDCBA ; promoted to JML
.proc long_rts : far
RTS ; promoted to RTL
.endproc