Merge pull request #1487 from mrdudz/wrapped-call

Extend #pragma wrapped-call to support "bank" argument
This commit is contained in:
Oliver Schmidt 2021-05-11 14:32:28 +02:00 committed by GitHub
commit bda5bf70ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 35 additions and 21 deletions

View file

@ -1390,7 +1390,12 @@ parameter with the <tt/#pragma/.
the <tt/Y/ register if it wraps any variadic functions (they have "<tt/.../" the <tt/Y/ register if it wraps any variadic functions (they have "<tt/.../"
in their prototypes). in their prototypes).
The identifier is an 8-bit number that's set into <tt/tmp4/. The identifier is an 8-bit number that's set into <tt/tmp4/. If the identifier
is "bank", then a <tt><url url="ca65.html#.BANK" name=".bank"></tt> operator will be used
to determine the number from the bank attribute defined in the linker config,
see <htmlurl url="ld65.html#MEMORY" name="Other MEMORY area attributes">. Note that
this currently implies that only the least significant 8 bits of the bank attribute
can be used.
The address of a wrapped function is passed in <tt/ptr4/. The wrapper can The address of a wrapped function is passed in <tt/ptr4/. The wrapper can
call that function by using "<tt/jsr callptr4/". call that function by using "<tt/jsr callptr4/".

View file

@ -760,7 +760,7 @@ There's a library subroutine called <tt/copydata/ (in a module named
look at it's inner workings before using it! look at it's inner workings before using it!
<sect1>Other MEMORY area attributes<p> <sect1>Other MEMORY area attributes<label id="MEMORY"><p>
There are some other attributes not covered above. Before starting the There are some other attributes not covered above. Before starting the
reference section, I will discuss the remaining things here. reference section, I will discuss the remaining things here.
@ -822,7 +822,6 @@ that has a segment reference (for example a symbol). The result of this
function is the value of the bank attribute for the run memory area of the function is the value of the bank attribute for the run memory area of the
segment. segment.
<sect1>Other SEGMENT attributes<p> <sect1>Other SEGMENT attributes<p>
Segments may be aligned to some memory boundary. Specify "<tt/align = num/" to Segments may be aligned to some memory boundary. Specify "<tt/align = num/" to

View file

@ -1738,7 +1738,7 @@ static FuncDesc* ParseFuncDecl (void)
{ {
SymEntry* Sym; SymEntry* Sym;
SymEntry* WrappedCall; SymEntry* WrappedCall;
unsigned char WrappedCallData; unsigned int WrappedCallData;
/* Create a new function descriptor */ /* Create a new function descriptor */
FuncDesc* F = NewFuncDesc (); FuncDesc* F = NewFuncDesc ();

View file

@ -997,9 +997,16 @@ static void FunctionCall (ExprDesc* Expr)
char tmp[64]; char tmp[64];
StrBuf S = AUTO_STRBUF_INITIALIZER; StrBuf S = AUTO_STRBUF_INITIALIZER;
/* Store the WrappedCall data in tmp4 */ if (Func->WrappedCallData == WRAPPED_CALL_USE_BANK) {
sprintf(tmp, "ldy #%u", Func->WrappedCallData); /* Store the bank attribute in tmp4 */
SB_AppendStr (&S, tmp); SB_AppendStr (&S, "ldy #<.bank(_");
SB_AppendStr (&S, (const char*) Expr->Name);
SB_AppendChar (&S, ')');
} else {
/* Store the WrappedCall data in tmp4 */
sprintf(tmp, "ldy #%u", Func->WrappedCallData);
SB_AppendStr (&S, tmp);
}
g_asmcode (&S); g_asmcode (&S);
SB_Clear(&S); SB_Clear(&S);

View file

@ -58,7 +58,7 @@
/* Bits that must be ignored when comparing funcs */ /* Bits that must be ignored when comparing funcs */
#define FD_IGNORE (FD_INCOMPLETE_PARAM | FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS | FD_CALL_WRAPPER) #define FD_IGNORE (FD_INCOMPLETE_PARAM | FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS | FD_CALL_WRAPPER)
#define WRAPPED_CALL_USE_BANK 0x0100U /* WrappedCall uses .bank() */
/* Function descriptor */ /* Function descriptor */
typedef struct FuncDesc FuncDesc; typedef struct FuncDesc FuncDesc;
@ -71,7 +71,7 @@ struct FuncDesc {
struct SymEntry* LastParam; /* Pointer to last parameter */ struct SymEntry* LastParam; /* Pointer to last parameter */
struct FuncDesc* FuncDef; /* Descriptor used in definition */ struct FuncDesc* FuncDef; /* Descriptor used in definition */
struct SymEntry* WrappedCall; /* Pointer to the WrappedCall */ struct SymEntry* WrappedCall; /* Pointer to the WrappedCall */
unsigned char WrappedCallData; /* The WrappedCall's user data */ unsigned int WrappedCallData; /* The WrappedCall's user data */
}; };

View file

@ -531,16 +531,19 @@ static void WrappedCallPragma (StrBuf* B)
/* Skip the following comma */ /* Skip the following comma */
if (!GetComma (B)) { if (!GetComma (B)) {
/* Error already flagged by GetComma */ /* Error already flagged by GetComma */
Error ("Value or the word 'bank' required for wrapped-call identifier");
goto ExitPoint;
}
/* Next must be either a numeric value, or "bank" */
if (HasStr (B, "bank")) {
Val = WRAPPED_CALL_USE_BANK;
} else if (!GetNumber (B, &Val)) {
Error ("Value required for wrapped-call identifier"); Error ("Value required for wrapped-call identifier");
goto ExitPoint; goto ExitPoint;
} }
if (!GetNumber (B, &Val)) { if (!(Val == WRAPPED_CALL_USE_BANK) && (Val < 0 || Val > 255)) {
Error ("Value required for wrapped-call identifier");
goto ExitPoint;
}
if (Val < 0 || Val > 255) {
Error ("Identifier must be between 0-255"); Error ("Identifier must be between 0-255");
goto ExitPoint; goto ExitPoint;
} }
@ -552,7 +555,7 @@ static void WrappedCallPragma (StrBuf* B)
/* Check if the name is valid */ /* Check if the name is valid */
if (Entry && (Entry->Flags & SC_FUNC) == SC_FUNC) { if (Entry && (Entry->Flags & SC_FUNC) == SC_FUNC) {
PushWrappedCall(Entry, (unsigned char) Val); PushWrappedCall(Entry, (unsigned int) Val);
Entry->Flags |= SC_REF; Entry->Flags |= SC_REF;
GetFuncDesc (Entry->Type)->Flags |= FD_CALL_WRAPPER; GetFuncDesc (Entry->Type)->Flags |= FD_CALL_WRAPPER;

View file

@ -64,7 +64,7 @@ static IntPtrStack WrappedCalls;
void PushWrappedCall (void *Ptr, unsigned char Val) void PushWrappedCall (void *Ptr, unsigned int Val)
/* Push the current WrappedCall */ /* Push the current WrappedCall */
{ {
if (IPS_IsFull (&WrappedCalls)) { if (IPS_IsFull (&WrappedCalls)) {
@ -88,7 +88,7 @@ void PopWrappedCall (void)
void GetWrappedCall (void **Ptr, unsigned char *Val) void GetWrappedCall (void **Ptr, unsigned int *Val)
/* Get the current WrappedCall */ /* Get the current WrappedCall */
{ {
if (IPS_GetCount (&WrappedCalls) < 1) { if (IPS_GetCount (&WrappedCalls) < 1) {
@ -97,6 +97,6 @@ void GetWrappedCall (void **Ptr, unsigned char *Val)
} else { } else {
long Temp; long Temp;
IPS_Get (&WrappedCalls, &Temp, Ptr); IPS_Get (&WrappedCalls, &Temp, Ptr);
*Val = (unsigned char) Temp; *Val = (unsigned int) Temp;
} }
} }

View file

@ -50,13 +50,13 @@
void PushWrappedCall (void *Ptr, unsigned char Val); void PushWrappedCall (void *Ptr, unsigned int Val);
/* Push the current WrappedCall */ /* Push the current WrappedCall */
void PopWrappedCall (void); void PopWrappedCall (void);
/* Pop the current WrappedCall */ /* Pop the current WrappedCall */
void GetWrappedCall (void **Ptr, unsigned char *Val); void GetWrappedCall (void **Ptr, unsigned int *Val);
/* Get the current WrappedCall, if any */ /* Get the current WrappedCall, if any */