ca65 jsr/jmp/rts will not promote to jsl/jml/rtl by default, but can still be enabled with new feature long_jsr_jmp_rts

This commit is contained in:
bbbradsmith
2023-02-21 04:00:34 -05:00
parent d0f17ba602
commit ccf3994e3b
6 changed files with 79 additions and 9 deletions

View File

@@ -183,7 +183,7 @@ Here is a description of all the command line options:
Enable an emulation feature. This is identical as using <tt/.FEATURE/ Enable an emulation feature. This is identical as using <tt/.FEATURE/
in the source with two exceptions: Feature names must be lower case, and 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. comma separated lists are not allowed.
See the discussion of the <tt><ref id=".FEATURE" name=".FEATURE"></tt> See the discussion of the <tt><ref id=".FEATURE" name=".FEATURE"></tt>
@@ -2825,6 +2825,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 overridden. When using this feature, you may also get into trouble if
later versions of the assembler define new keywords starting with a dot. 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> <tag><tt>loose_char_term</tt><label id="loose_char_term"></tag>
Accept single quotes as well as double quotes as terminators for char Accept single quotes as well as double quotes as terminators for char
@@ -3994,7 +4011,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 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/ results in some cases. If in doubt, use the <tt/.Inn/ and <tt/.Ann/
instructions to tell the assembler about the current settings. 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 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 no explicit address specification, but it is <tt/far/ because of the
memory model used. memory model used.

View File

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

View File

@@ -68,6 +68,7 @@ typedef enum {
FEAT_ADDRSIZE, FEAT_ADDRSIZE,
FEAT_BRACKET_AS_INDIRECT, FEAT_BRACKET_AS_INDIRECT,
FEAT_STRING_ESCAPES, FEAT_STRING_ESCAPES,
FEAT_LONG_JSR_JMP_RTS,
/* Special value: Number of features available */ /* Special value: Number of features available */
FEAT_COUNT 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 LargeAlignment = 0; /* Don't warn about large alignments */
unsigned char RelaxChecks = 0; /* Relax a few assembler checks */ unsigned char RelaxChecks = 0; /* Relax a few assembler checks */
unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */ unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */
unsigned char LongJsrJmpRts = 0; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
/* Emulation features */ /* Emulation features */
unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */ unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */

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 LargeAlignment; /* Don't warn about large alignments */
extern unsigned char RelaxChecks; /* Relax a few assembler checks */ extern unsigned char RelaxChecks; /* Relax a few assembler checks */
extern unsigned char StringEscapes; /* Allow C-style escapes in strings */ extern unsigned char StringEscapes; /* Allow C-style escapes in strings */
extern unsigned char LongJsrJmpRts; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
/* Emulation features */ /* Emulation features */
extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */ extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */

View File

@@ -120,9 +120,21 @@ static void PutJMP (const InsDesc* Ins);
** to check for this case and is otherwise identical to PutAll. ** 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))); static void PutRTS (const InsDesc* Ins attribute ((unused)));
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if /* 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); static void PutAll (const InsDesc* Ins);
@@ -758,9 +770,9 @@ static const struct {
{ "INX", 0x0000001, 0xe8, 0, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll },
{ "JML", 0x4000010, 0x5c, 1, PutAll }, { "JML", 0x4000010, 0x5c, 1, PutAll },
{ "JMP", 0x4010818, 0x4c, 6, PutAll }, { "JMP", 0x4010818, 0x4c, 6, PutJMP816 },
{ "JSL", 0x0000010, 0x20, 7, PutAll }, { "JSL", 0x0000010, 0x20, 7, PutAll },
{ "JSR", 0x0010018, 0x20, 7, PutAll }, { "JSR", 0x0010018, 0x20, 7, PutJSR816 },
{ "LDA", 0x0b8f6fc, 0xa0, 0, PutAll }, { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
{ "LDX", 0x0c0030c, 0xa2, 1, PutAll }, { "LDX", 0x0c0030c, 0xa2, 1, PutAll },
{ "LDY", 0x0c0006c, 0xa0, 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))) static void PutJMP816 (const InsDesc* Ins)
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if /* Handle the JMP instruction for the 816.
** the enclosing scope is FAR. ** 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 */ Emit0 (0x6B); /* RTL */
} else { } else {
Emit0 (0x60); /* RTS */ Emit0 (0x60); /* RTS */