1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 07:29:33 +00:00

Support for optionally specifying address size for segments with:

#pragma ***-name([push,] "name"[, "addrsize"])
where "addrsize" is any addressing size supported in ca65.
This commit is contained in:
acqn 2020-01-21 10:39:19 +08:00 committed by Oliver Schmidt
parent f8c9dde989
commit e58c84acf7
5 changed files with 148 additions and 3 deletions

View File

@ -39,6 +39,7 @@
#include <stdarg.h>
/* common */
#include "addrsize.h"
#include "check.h"
#include "cpu.h"
#include "inttypes.h"
@ -260,6 +261,9 @@ void g_usebss (void)
void g_segname (segment_t Seg)
/* Emit the name of a segment if necessary */
{
unsigned char AddrSize;
const char* Name;
/* Emit a segment directive for the data style segments */
DataSeg* S;
switch (Seg) {
@ -269,7 +273,13 @@ void g_segname (segment_t Seg)
default: S = 0; break;
}
if (S) {
DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg));
Name = GetSegName (Seg);
AddrSize = GetSegAddrSize (Name);
if (AddrSize != ADDR_SIZE_INVALID) {
DS_AddLine (S, ".segment\t\"%s\": %s", Name, AddrSizeToStr (AddrSize));
} else {
DS_AddLine (S, ".segment\t\"%s\"", Name);
}
}
}

View File

@ -897,6 +897,9 @@ int main (int argc, char* argv[])
/* Initialize the default segment names */
InitSegNames ();
/* Initialize the segment address sizes table */
InitSegAddrSizes ();
/* Initialize the include search paths */
InitIncludePaths ();
@ -1089,6 +1092,9 @@ int main (int argc, char* argv[])
/* Done with tracked string buffer allocation */
DoneDiagnosticStrBufs ();
/* Free up the segment address sizes table */
DoneSegAddrSizes ();
/* Return an apropriate exit code */
return (ErrorCount > 0)? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -37,6 +37,7 @@
#include <string.h>
/* common */
#include "addrsize.h"
#include "chartype.h"
#include "segnames.h"
#include "tgttrans.h"
@ -389,7 +390,9 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
/* Handle a pragma that expects a segment name parameter */
{
const char* Name;
unsigned char AddrSize = ADDR_SIZE_INVALID;
StrBuf S = AUTO_STRBUF_INITIALIZER;
StrBuf A = AUTO_STRBUF_INITIALIZER;
int Push = 0;
/* Check for the "push" or "pop" keywords */
@ -430,13 +433,35 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
goto ExitPoint;
}
/* Get the string */
/* Get the name string of the segment */
Name = SB_GetConstBuf (&S);
/* Check if the name is valid */
if (ValidSegName (Name)) {
/* Set the new name */
/* Skip the following comma */
SB_SkipWhite (B);
if (SB_Peek (B) == ',') {
SB_Skip (B);
SB_SkipWhite (B);
/* A string argument must follow */
if (!GetString (B, &A)) {
goto ExitPoint;
}
/* Get the address size for the segment */
AddrSize = AddrSizeFromStr (SB_GetConstBuf (&A));
/* Set the address size for the segment if valid */
if (AddrSize != ADDR_SIZE_INVALID) {
SetSegAddrSize (Name, AddrSize);
} else {
Warning ("Invalid address size for segment!");
}
}
/* Set the new name and optionally address size */
if (Push) {
PushSegName (Seg, Name);
} else {
@ -460,6 +485,7 @@ static void SegNamePragma (StrBuf* B, segment_t Seg)
ExitPoint:
/* Call the string buf destructor */
SB_Done (&S);
SB_Done (&A);
}

View File

@ -37,6 +37,7 @@
#include <string.h>
/* common */
#include "addrsize.h"
#include "chartype.h"
#include "check.h"
#include "coll.h"
@ -61,6 +62,13 @@
/* Table struct for address sizes of segments */
typedef struct {
StrBuf Name;
unsigned char AddrSize;
} SegAddrSize_t;
/* Pointer to the current segment list. Output goes here. */
Segments* CS = 0;
@ -70,6 +78,9 @@ Segments* GS = 0;
/* Actual names for the segments */
static StrStack SegmentNames[SEG_COUNT];
/* Address size for the segments */
static Collection SegmentAddrSizes;
/* We're using a collection for the stack instead of a linked list. Since
** functions may not be nested (at least in the current implementation), the
** maximum stack depth is 2, so there is not really a need for a better
@ -85,6 +96,85 @@ static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
void InitSegAddrSizes (void)
/* Initialize the segment address sizes */
{
InitCollection (&SegmentAddrSizes);
}
void DoneSegAddrSizes (void)
/* Free the segment address sizes */
{
SegAddrSize_t* A;
int I;
for (I = 0; I < (int)CollCount (&SegmentAddrSizes); ++I) {
A = CollAtUnchecked (&SegmentAddrSizes, I);
SB_Done (&A->Name);
xfree (A);
}
DoneCollection (&SegmentAddrSizes);
}
static SegAddrSize_t* FindSegAddrSize (const char* Name)
/* Find already specified address size for a segment by name.
** Return the found struct or 0 if not found.
*/
{
SegAddrSize_t* A;
int I;
for (I = 0; I < (int)CollCount (&SegmentAddrSizes); ++I) {
A = CollAtUnchecked (&SegmentAddrSizes, I);
if (A && strcmp (SB_GetConstBuf (&A->Name), Name) == 0) {
return A;
}
}
return 0;
}
void SetSegAddrSize (const char* Name, unsigned char AddrSize)
/* Set the address size for a segment */
{
SegAddrSize_t* A = FindSegAddrSize (Name);
if (!A) {
/* New one */
A = xmalloc (sizeof (SegAddrSize_t));
SB_Init (&A->Name);
SB_CopyStr (&A->Name, Name);
SB_Terminate (&A->Name);
CollAppend (&SegmentAddrSizes, A);
} else {
/* Check for mismatching address sizes */
if (A->AddrSize != AddrSize) {
Warning ("Segment address size changed from last time!");
}
}
/* Set the address size anyway */
A->AddrSize = AddrSize;
}
unsigned char GetSegAddrSize (const char* Name)
/* Get the address size of the given segment.
** Return ADDR_SIZE_INVALID if not found.
*/
{
SegAddrSize_t* A = FindSegAddrSize (Name);
if (A) {
return A->AddrSize;
}
return ADDR_SIZE_INVALID;
}
void InitSegNames (void)
/* Initialize the segment names */
{

View File

@ -103,6 +103,19 @@ extern Segments* GS;
/*****************************************************************************/
void InitSegAddrSizes (void);
/* Initialize the segment address sizes */
void DoneSegAddrSizes (void);
/* Free the segment address sizes */
void SetSegAddrSize (const char* Name, unsigned char AddrSize);
/* Set the address size for a segment */
unsigned char GetSegAddrSize (const char* Name);
/* Get the address size of the given segment.
** Return ADDR_SIZE_INVALID if not found.
*/
void InitSegNames (void);
/* Initialize the segment names */