diff --git a/doc/da65.sgml b/doc/da65.sgml index a8e32e1c8..54a341615 100644 --- a/doc/da65.sgml +++ b/doc/da65.sgml @@ -542,6 +542,18 @@ code. The following attributes are recognized: range, where PARAMSIZE + This optional attribute is followed by a numerical value. It tells the + assembler that subroutine calls to this label are followed by + "inline parameters" with the given number of bytes, like this: + + + JSR LabelWithParamSize2 + .byte $00, $10 + (return here) + code... + + diff --git a/src/da65/handler.c b/src/da65/handler.c index 624952363..f8a778b22 100644 --- a/src/da65/handler.c +++ b/src/da65/handler.c @@ -51,6 +51,8 @@ +static unsigned short SubroutineParamSize[0x10000]; + /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ @@ -741,3 +743,35 @@ void OH_JmpAbsoluteXIndirect (const OpcDesc* D) } SeparatorLine (); } + + + +void OH_JsrAbsolute (const OpcDesc* D) +{ + unsigned ParamSize = SubroutineParamSize[GetCodeWord (PC+1)]; + OH_Absolute (D); + if (ParamSize > 0) { + unsigned RemainingBytes; + unsigned BytesLeft; + PC += D->Size; + RemainingBytes = GetRemainingBytes (); + if (RemainingBytes < ParamSize) { + ParamSize = RemainingBytes; + } + BytesLeft = ParamSize; + while (BytesLeft > 0) { + unsigned Chunk = (BytesLeft > BytesPerLine) ? BytesPerLine : BytesLeft; + DataByteLine (Chunk); + BytesLeft -= Chunk; + PC += Chunk; + } + PC -= D->Size; + } +} + + + +void SetSubroutineParamSize (unsigned Addr, unsigned Size) +{ + SubroutineParamSize[Addr] = Size; +} diff --git a/src/da65/handler.h b/src/da65/handler.h index c0fa68e56..eaa66e7fd 100644 --- a/src/da65/handler.h +++ b/src/da65/handler.h @@ -104,7 +104,9 @@ void OH_Rts (const OpcDesc*); void OH_JmpAbsolute (const OpcDesc*); void OH_JmpAbsoluteIndirect (const OpcDesc* D); void OH_JmpAbsoluteXIndirect (const OpcDesc* D); +void OH_JsrAbsolute (const OpcDesc*); +void SetSubroutineParamSize (unsigned Addr, unsigned Size); /* End of handler.h */ diff --git a/src/da65/infofile.c b/src/da65/infofile.c index e8ce66cf7..6db82cb36 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -59,6 +59,7 @@ #include "opctable.h" #include "scanner.h" #include "segment.h" +#include "handler.h" @@ -376,17 +377,19 @@ static void LabelSection (void) /* Parse a label section */ { static const IdentTok LabelDefs[] = { - { "COMMENT", INFOTOK_COMMENT }, - { "ADDR", INFOTOK_ADDR }, - { "NAME", INFOTOK_NAME }, - { "SIZE", INFOTOK_SIZE }, + { "COMMENT", INFOTOK_COMMENT }, + { "ADDR", INFOTOK_ADDR }, + { "NAME", INFOTOK_NAME }, + { "SIZE", INFOTOK_SIZE }, + { "PARAMSIZE", INFOTOK_PARAMSIZE }, }; /* Locals - initialize to avoid gcc warnings */ - char* Name = 0; - char* Comment = 0; - long Value = -1; - long Size = -1; + char* Name = 0; + char* Comment = 0; + long Value = -1; + long Size = -1; + long ParamSize = -1; /* Skip the token */ InfoNextTok (); @@ -448,6 +451,17 @@ static void LabelSection (void) InfoNextTok (); break; + case INFOTOK_PARAMSIZE: + InfoNextTok (); + if (ParamSize >= 0) { + InfoError ("ParamSize already given"); + } + InfoAssureInt (); + InfoRangeCheck (1, 0x10000); + ParamSize = InfoIVal; + InfoNextTok (); + break; + default: Internal ("Unexpected token: %u", InfoTok); } @@ -484,6 +498,9 @@ static void LabelSection (void) } else { AddExtLabelRange ((unsigned) Value, Name, Size); } + if (ParamSize >= 0) { + SetSubroutineParamSize ((unsigned) Value, (unsigned) ParamSize); + } /* Define the comment */ if (Comment) { diff --git a/src/da65/opc6502.c b/src/da65/opc6502.c index 27f734d56..8fc6f6aea 100644 --- a/src/da65/opc6502.c +++ b/src/da65/opc6502.c @@ -79,7 +79,7 @@ const OpcDesc OpcTable_6502[256] = { { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "", 1, flIllegal, OH_Illegal, }, /* $1f */ - { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ + { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "", 1, flIllegal, OH_Illegal, }, /* $22 */ { "", 1, flIllegal, OH_Illegal, }, /* $23 */ diff --git a/src/da65/opc65816.c b/src/da65/opc65816.c index 2cd2aaee8..b7775d2e2 100644 --- a/src/da65/opc65816.c +++ b/src/da65/opc65816.c @@ -79,7 +79,7 @@ const OpcDesc OpcTable_65816[256] = { { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "ora", 4, flUseLabel, OH_AbsoluteLongX }, /* $1f */ - { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ + { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "jsl", 3, flLabel, OH_AbsoluteLong }, /* $22 */ { "and", 2, flNone, OH_StackRelative }, /* $23 */ diff --git a/src/da65/opc65c02.c b/src/da65/opc65c02.c index 8133bccae..b69558f2a 100644 --- a/src/da65/opc65c02.c +++ b/src/da65/opc65c02.c @@ -79,7 +79,7 @@ const OpcDesc OpcTable_65C02[256] = { { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "bbr1", 3, flUseLabel, OH_BitBranch }, /* $1f */ - { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ + { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "", 1, flIllegal, OH_Illegal, }, /* $22 */ { "", 1, flIllegal, OH_Illegal, }, /* $23 */ diff --git a/src/da65/opc65sc02.c b/src/da65/opc65sc02.c index 90549d00f..82e10bd96 100644 --- a/src/da65/opc65sc02.c +++ b/src/da65/opc65sc02.c @@ -79,7 +79,7 @@ const OpcDesc OpcTable_65SC02[256] = { { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "", 1, flIllegal, OH_Illegal, }, /* $1f */ - { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ + { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "", 1, flIllegal, OH_Illegal, }, /* $22 */ { "", 1, flIllegal, OH_Illegal, }, /* $23 */ diff --git a/src/da65/scanner.h b/src/da65/scanner.h index f7f090fad..d4e38177b 100644 --- a/src/da65/scanner.h +++ b/src/da65/scanner.h @@ -105,6 +105,7 @@ typedef enum token_t { INFOTOK_COMMENT, INFOTOK_ADDR, INFOTOK_SIZE, + INFOTOK_PARAMSIZE, /* ASMINC section */ INFOTOK_FILE,