1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-14 00:32:08 +00:00

New .PUSHSEG and .POPSEG commands

git-svn-id: svn://svn.cc65.org/cc65/trunk@1671 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2002-11-28 17:42:16 +00:00
parent cf2162f5da
commit 1167d99a9b
9 changed files with 155 additions and 143 deletions

View File

@ -184,6 +184,9 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap)
"Conditional assembly branch was never closed", "Conditional assembly branch was never closed",
"Lexical level was not terminated correctly", "Lexical level was not terminated correctly",
"Segment attribute mismatch", "Segment attribute mismatch",
"Segment stack overflow",
"Segment stack is empty",
"Segment stack is not empty at end of assembly",
"CPU not supported", "CPU not supported",
"Counter underflow", "Counter underflow",
"Undefined label", "Undefined label",

View File

@ -44,14 +44,14 @@
/*****************************************************************************/ /*****************************************************************************/
/* Data */ /* Data */
/*****************************************************************************/ /*****************************************************************************/
/* Warning numbers */ /* Warning numbers */
enum Warnings { enum Warnings {
WARN_NONE, /* No warning */ WARN_NONE, /* No warning */
WARN_MASK_ERROR, WARN_MASK_ERROR,
WARN_SYM_NOT_REFERENCED, WARN_SYM_NOT_REFERENCED,
WARN_IMPORT_NOT_REFERENCED, WARN_IMPORT_NOT_REFERENCED,
@ -125,6 +125,9 @@ enum Errors {
ERR_OPEN_IF, ERR_OPEN_IF,
ERR_OPEN_PROC, ERR_OPEN_PROC,
ERR_SEG_ATTR_MISMATCH, ERR_SEG_ATTR_MISMATCH,
ERR_SEGSTACK_OVERFLOW,
ERR_SEGSTACK_EMPTY,
ERR_SEGSTACK_NOT_EMPTY,
ERR_CPU_NOT_SUPPORTED, ERR_CPU_NOT_SUPPORTED,
ERR_COUNTER_UNDERFLOW, ERR_COUNTER_UNDERFLOW,
ERR_UNDEFINED_LABEL, ERR_UNDEFINED_LABEL,

View File

@ -621,6 +621,11 @@ int main (int argc, char* argv [])
/* Assemble the input */ /* Assemble the input */
Assemble (); Assemble ();
/* If we didn't have any errors, check the segment stack */
if (ErrorCount == 0) {
SegStackCheck ();
}
/* If we didn't have any errors, check the unnamed labels */ /* If we didn't have any errors, check the unnamed labels */
if (ErrorCount == 0) { if (ErrorCount == 0) {
ULabCheck (); ULabCheck ();

View File

@ -70,36 +70,33 @@ unsigned long AbsPC = 0; /* PC if in absolute mode */
typedef struct Segment Segment; typedef struct Segment Segment;
struct Segment { struct Segment {
Segment* List; /* List of all segments */ Segment* List; /* List of all segments */
Fragment* Root; /* Root of fragment list */ Fragment* Root; /* Root of fragment list */
Fragment* Last; /* Pointer to last fragment */ Fragment* Last; /* Pointer to last fragment */
unsigned char Align; /* Segment alignment */ unsigned Num; /* Segment number */
unsigned char SegType; /* True if zero page segment */ unsigned Align; /* Segment alignment */
unsigned long PC; unsigned long PC;
unsigned Num; /* Segment number */ SegDef* Def; /* Segment definition (name and type) */
char* Name; /* Segment name */
}; };
#define SEG(segdef, num, prev) \
{ prev, 0, 0, num, 0, 0, segdef }
/* Definitions for predefined segments */
SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER ("NULL", SEGTYPE_ABS);
SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER ("ZEROPAGE", SEGTYPE_ZP);
SegDef DataSegDef = STATIC_SEGDEF_INITIALIZER ("DATA", SEGTYPE_ABS);
SegDef BssSegDef = STATIC_SEGDEF_INITIALIZER ("BSS", SEGTYPE_ABS);
SegDef RODataSegDef = STATIC_SEGDEF_INITIALIZER ("RODATA", SEGTYPE_ABS);
SegDef CodeSegDef = STATIC_SEGDEF_INITIALIZER ("CODE", SEGTYPE_ABS);
/* Predefined segments */ /* Predefined segments */
static Segment NullSeg = { static Segment NullSeg = SEG (&NullSegDef, 5, NULL);
0, 0, 0, 0, SEGTYPE_ABS, 0, 5, "NULL" static Segment ZeropageSeg = SEG (&ZeropageSegDef, 4, &NullSeg);
}; static Segment DataSeg = SEG (&DataSegDef, 3, &ZeropageSeg);
static Segment ZeropageSeg = { static Segment BssSeg = SEG (&BssSegDef, 2, &DataSeg);
&NullSeg, 0, 0, 0, SEGTYPE_ZP, 0, 4, "ZEROPAGE" static Segment RODataSeg = SEG (&RODataSegDef, 1, &BssSeg);
}; static Segment CodeSeg = SEG (&CodeSegDef, 0, &RODataSeg);
static Segment DataSeg = {
&ZeropageSeg, 0, 0, 0, SEGTYPE_ABS, 0, 3, "DATA"
};
static Segment BssSeg = {
&DataSeg, 0, 0, 0, SEGTYPE_ABS, 0, 2, "BSS"
};
static Segment RODataSeg = {
&BssSeg, 0, 0, 0, SEGTYPE_ABS, 0, 1, "RODATA"
};
static Segment CodeSeg = {
&RODataSeg, 0, 0, 0, SEGTYPE_ABS, 0, 0, "CODE"
};
/* Number of segments */ /* Number of segments */
static unsigned SegmentCount = 6; static unsigned SegmentCount = 6;
@ -123,7 +120,6 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
/* Create a new segment, insert it into the global list and return it */ /* Create a new segment, insert it into the global list and return it */
{ {
Segment* S; Segment* S;
const char* N;
/* Check for too many segments */ /* Check for too many segments */
if (SegmentCount >= 256) { if (SegmentCount >= 256) {
@ -131,30 +127,21 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
} }
/* Check the segment name for invalid names */ /* Check the segment name for invalid names */
N = Name; if (!ValidSegName (Name)) {
if ((*N != '_' && !IsAlpha (*N)) || strlen (Name) > 80) {
Error (ERR_ILLEGAL_SEGMENT, Name); Error (ERR_ILLEGAL_SEGMENT, Name);
} }
do {
if (*N != '_' && !IsAlNum (*N)) {
Error (ERR_ILLEGAL_SEGMENT, Name);
break;
}
++N;
} while (*N);
/* Create a new segment */ /* Create a new segment */
S = xmalloc (sizeof (*S)); S = xmalloc (sizeof (*S));
/* Initialize it */ /* Initialize it */
S->List = 0; S->List = 0;
S->Root = 0; S->Root = 0;
S->Last = 0; S->Last = 0;
S->Align = 0; S->Num = SegmentCount++;
S->SegType = SegType; S->Align = 0;
S->PC = 0; S->PC = 0;
S->Num = SegmentCount++; S->Def = NewSegDef (Name, SegType);
S->Name = xstrdup (Name);
/* Insert it into the segment list */ /* Insert it into the segment list */
SegmentLast->List = S; SegmentLast->List = S;
@ -166,65 +153,17 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
void UseCodeSeg (void) void UseSeg (const SegDef* D)
/* Use the code segment */
{
ActiveSeg = &CodeSeg;
}
void UseRODataSeg (void)
/* Use the r/o data segment */
{
ActiveSeg = &RODataSeg;
}
void UseDataSeg (void)
/* Use the data segment */
{
ActiveSeg = &DataSeg;
}
void UseBssSeg (void)
/* Use the BSS segment */
{
ActiveSeg = &BssSeg;
}
void UseZeropageSeg (void)
/* Use the zero page segment */
{
ActiveSeg = &ZeropageSeg;
}
void UseNullSeg (void)
/* Use the null segment */
{
ActiveSeg = &NullSeg;
}
void UseSeg (const char* Name, unsigned SegType)
/* Use the segment with the given name */ /* Use the segment with the given name */
{ {
Segment* Seg = SegmentList; Segment* Seg = SegmentList;
while (Seg) { while (Seg) {
if (strcmp (Seg->Name, Name) == 0) { if (strcmp (Seg->Def->Name, D->Name) == 0) {
/* We found this segment. Check if the type is identical */ /* We found this segment. Check if the type is identical */
if (SegType != SEGTYPE_DEFAULT && Seg->SegType != SegType) { if (D->Type != SEGTYPE_DEFAULT && Seg->Def->Type != D->Type) {
Error (ERR_SEG_ATTR_MISMATCH); Error (ERR_SEG_ATTR_MISMATCH);
/* Use the new attribute to avoid errors */ /* Use the new attribute to avoid errors */
Seg->SegType = SegType; Seg->Def->Type = D->Type;
} }
ActiveSeg = Seg; ActiveSeg = Seg;
return; return;
@ -234,10 +173,11 @@ void UseSeg (const char* Name, unsigned SegType)
} }
/* Segment is not in list, create a new one */ /* Segment is not in list, create a new one */
if (SegType == SEGTYPE_DEFAULT) { if (D->Type == SEGTYPE_DEFAULT) {
SegType = SEGTYPE_ABS; Seg = NewSegment (D->Name, SEGTYPE_ABS);
} else {
Seg = NewSegment (D->Name, D->Type);
} }
Seg = NewSegment (Name, SegType);
ActiveSeg = Seg; ActiveSeg = Seg;
} }
@ -260,6 +200,14 @@ void SetAbsPC (unsigned long PC)
const SegDef* GetCurrentSeg (void)
/* Get a pointer to the segment defininition of the current segment */
{
return ActiveSeg->Def;
}
unsigned GetSegNum (void) unsigned GetSegNum (void)
/* Get the number of the current segment */ /* Get the number of the current segment */
{ {
@ -307,7 +255,7 @@ void SegAlign (unsigned Power, int Val)
int IsZPSeg (void) int IsZPSeg (void)
/* Return true if the current segment is a zeropage segment */ /* Return true if the current segment is a zeropage segment */
{ {
return (ActiveSeg->SegType == SEGTYPE_ZP); return (ActiveSeg->Def->Type == SEGTYPE_ZP);
} }
@ -315,7 +263,7 @@ int IsZPSeg (void)
int IsFarSeg (void) int IsFarSeg (void)
/* Return true if the current segment is a far segment */ /* Return true if the current segment is a far segment */
{ {
return (ActiveSeg->SegType == SEGTYPE_FAR); return (ActiveSeg->Def->Type == SEGTYPE_FAR);
} }
@ -336,7 +284,7 @@ unsigned GetSegType (unsigned SegNum)
} }
/* Return the segment type */ /* Return the segment type */
return S->SegType; return S->Def->Type;
} }
@ -418,7 +366,7 @@ void SegDump (void)
unsigned I; unsigned I;
Fragment* F; Fragment* F;
int State = -1; int State = -1;
printf ("New segment: %s", S->Name); printf ("New segment: %s", S->Def->Name);
F = S->Root; F = S->Root;
while (F) { while (F) {
if (F->Type == FRAG_LITERAL) { if (F->Type == FRAG_LITERAL) {
@ -461,10 +409,10 @@ static void WriteOneSeg (Segment* Seg)
unsigned LineInfoIndex; unsigned LineInfoIndex;
/* Write the segment name followed by the byte count in this segment */ /* Write the segment name followed by the byte count in this segment */
ObjWriteStr (Seg->Name); ObjWriteStr (Seg->Def->Name);
ObjWrite32 (Seg->PC); ObjWrite32 (Seg->PC);
ObjWrite8 (Seg->Align); ObjWrite8 (Seg->Align);
ObjWrite8 (Seg->SegType); ObjWrite8 (Seg->Def->Type);
/* Now walk through the fragment list for this segment and write the /* Now walk through the fragment list for this segment and write the
* fragments. * fragments.

View File

@ -55,6 +55,14 @@
/* Are we in absolute mode or in relocatable mode? */ /* Are we in absolute mode or in relocatable mode? */
extern int RelocMode; extern int RelocMode;
/* Definitions for predefined segments */
SegDef NullSegDef;
SegDef ZeropageSegDef;
SegDef DataSegDef;
SegDef BssSegDef;
SegDef RODataSegDef;
SegDef CodeSegDef;
/*****************************************************************************/ /*****************************************************************************/
@ -63,26 +71,11 @@ extern int RelocMode;
void UseCodeSeg (void); void UseSeg (const SegDef* D);
/* Use the code segment */ /* Use the given segment */
void UseRODataSeg (void); const SegDef* GetCurrentSeg (void);
/* Use the r/o data segment */ /* Get a pointer to the segment defininition of the current segment */
void UseDataSeg (void);
/* Use the data segment */
void UseBssSeg (void);
/* Use the BSS segment */
void UseZeropageSeg (void);
/* Use the zero page segment */
void UseNullSeg (void);
/* Use the null segment */
void UseSeg (const char* Name, unsigned SegType);
/* Use the segment with the given name */
unsigned GetSegNum (void); unsigned GetSegNum (void);
/* Get the number of the current segment */ /* Get the number of the current segment */

View File

@ -42,7 +42,7 @@
/* common */ /* common */
#include "bitops.h" #include "bitops.h"
#include "cddefs.h" #include "cddefs.h"
#include "check.h" #include "coll.h"
#include "symdefs.h" #include "symdefs.h"
#include "tgttrans.h" #include "tgttrans.h"
@ -75,6 +75,10 @@
/* Keyword we're about to handle */ /* Keyword we're about to handle */
static char Keyword [sizeof (SVal)+1] = "."; static char Keyword [sizeof (SVal)+1] = ".";
/* Segment stack */
#define MAX_PUSHED_SEGMENTS 16
static Collection SegStack = STATIC_COLLECTION_INITIALIZER;
/*****************************************************************************/ /*****************************************************************************/
@ -331,7 +335,7 @@ static void DoAutoImport (void)
static void DoBss (void) static void DoBss (void)
/* Switch to the BSS segment */ /* Switch to the BSS segment */
{ {
UseBssSeg (); UseSeg (&BssSegDef);
} }
@ -407,7 +411,7 @@ static void DoCharMap (void)
static void DoCode (void) static void DoCode (void)
/* Switch to the code segment */ /* Switch to the code segment */
{ {
UseCodeSeg (); UseSeg (&CodeSegDef);
} }
@ -485,7 +489,7 @@ static void DoConstructor (void)
static void DoData (void) static void DoData (void)
/* Switch to the data segment */ /* Switch to the data segment */
{ {
UseDataSeg (); UseSeg (&DataSegDef);
} }
@ -1059,7 +1063,7 @@ static void DoMacro (void)
static void DoNull (void) static void DoNull (void)
/* Switch to the NULL segment */ /* Switch to the NULL segment */
{ {
UseNullSeg (); UseSeg (&NullSegDef);
} }
@ -1126,6 +1130,29 @@ static void DoPageLength (void)
static void DoPopSeg (void)
/* Pop an old segment from the segment stack */
{
SegDef* Def;
/* Must have a segment on the stack */
if (CollCount (&SegStack) == 0) {
ErrorSkip (ERR_SEGSTACK_EMPTY);
return;
}
/* Pop the last element */
Def = CollPop (&SegStack);
/* Restore this segment */
UseSeg (Def);
/* Delete the segment definition */
FreeSegDef (Def);
}
static void DoProc (void) static void DoProc (void)
/* Start a new lexical scope */ /* Start a new lexical scope */
{ {
@ -1139,6 +1166,21 @@ static void DoProc (void)
static void DoPushSeg (void)
/* Push the current segment onto the segment stack */
{
/* Can only push a limited size of segments */
if (CollCount (&SegStack) >= MAX_PUSHED_SEGMENTS) {
ErrorSkip (ERR_SEGSTACK_OVERFLOW);
return;
}
/* Get the current segment and push it */
CollAppend (&SegStack, DupSegDef (GetCurrentSeg ()));
}
static void DoReloc (void) static void DoReloc (void)
/* Enter relocatable mode */ /* Enter relocatable mode */
{ {
@ -1191,7 +1233,7 @@ static void DoRes (void)
static void DoROData (void) static void DoROData (void)
/* Switch to the r/o data segment */ /* Switch to the r/o data segment */
{ {
UseRODataSeg (); UseSeg (&RODataSegDef);
} }
@ -1205,7 +1247,7 @@ static void DoSegment (void)
"FAR", "LONG" "FAR", "LONG"
}; };
char Name [sizeof (SVal)]; char Name [sizeof (SVal)];
int SegType; SegDef Def = { Name, SEGTYPE_DEFAULT };
if (Tok != TOK_STRCON) { if (Tok != TOK_STRCON) {
ErrorSkip (ERR_STRCON_EXPECTED); ErrorSkip (ERR_STRCON_EXPECTED);
@ -1216,7 +1258,6 @@ static void DoSegment (void)
NextTok (); NextTok ();
/* Check for an optional segment attribute */ /* Check for an optional segment attribute */
SegType = SEGTYPE_DEFAULT;
if (Tok == TOK_COMMA) { if (Tok == TOK_COMMA) {
NextTok (); NextTok ();
if (Tok != TOK_IDENT) { if (Tok != TOK_IDENT) {
@ -1228,18 +1269,18 @@ static void DoSegment (void)
case 0: case 0:
case 1: case 1:
/* Zeropage */ /* Zeropage */
SegType = SEGTYPE_ZP; Def.Type = SEGTYPE_ZP;
break; break;
case 2: case 2:
/* Absolute */ /* Absolute */
SegType = SEGTYPE_ABS; Def.Type = SEGTYPE_ABS;
break; break;
case 3: case 3:
case 4: case 4:
/* Far */ /* Far */
SegType = SEGTYPE_FAR; Def.Type = SEGTYPE_FAR;
break; break;
default: default:
@ -1250,7 +1291,7 @@ static void DoSegment (void)
} }
/* Set the segment */ /* Set the segment */
UseSeg (Name, SegType); UseSeg (&Def);
} }
} }
@ -1312,7 +1353,7 @@ static void DoWord (void)
static void DoZeropage (void) static void DoZeropage (void)
/* Switch to the zeropage segment */ /* Switch to the zeropage segment */
{ {
UseZeropageSeg (); UseSeg (&ZeropageSegDef);
} }
@ -1416,7 +1457,9 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoPageLength }, { ccNone, DoPageLength },
{ ccNone, DoUnexpected }, /* .PARAMCOUNT */ { ccNone, DoUnexpected }, /* .PARAMCOUNT */
{ ccNone, DoPC02 }, { ccNone, DoPC02 },
{ ccNone, DoPopSeg },
{ ccNone, DoProc }, { ccNone, DoProc },
{ ccNone, DoPushSeg },
{ ccNone, DoUnexpected }, /* .REFERENCED */ { ccNone, DoUnexpected }, /* .REFERENCED */
{ ccNone, DoReloc }, { ccNone, DoReloc },
{ ccNone, DoRepeat }, { ccNone, DoRepeat },
@ -1440,7 +1483,7 @@ static CtrlDesc CtrlCmdTab [] = {
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
@ -1483,3 +1526,13 @@ void HandlePseudo (void)
void SegStackCheck (void)
/* Check if the segment stack is empty at end of assembly */
{
if (CollCount (&SegStack) != 0) {
Error (ERR_SEGSTACK_NOT_EMPTY);
}
}

View File

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998 Ullrich von Bassewitz */ /* (C) 1998-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* Wacholderweg 14 */
/* D-70597 Stuttgart */ /* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */ /* EMail: uz@musoftware.de */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -64,6 +64,9 @@ int TokIsPseudo (unsigned Tok);
void HandlePseudo (void); void HandlePseudo (void);
/* Handle a pseudo instruction */ /* Handle a pseudo instruction */
void SegStackCheck (void);
/* Check if the segment stack is empty at end of assembly */
/* End of pseudo.h */ /* End of pseudo.h */

View File

@ -211,7 +211,9 @@ struct DotKeyword {
{ ".PAGELENGTH", TOK_PAGELENGTH }, { ".PAGELENGTH", TOK_PAGELENGTH },
{ ".PARAMCOUNT", TOK_PARAMCOUNT }, { ".PARAMCOUNT", TOK_PARAMCOUNT },
{ ".PC02", TOK_PC02 }, { ".PC02", TOK_PC02 },
{ ".POPSEG", TOK_POPSEG },
{ ".PROC", TOK_PROC }, { ".PROC", TOK_PROC },
{ ".PUSHSEG", TOK_PUSHSEG },
{ ".REF", TOK_REFERENCED }, { ".REF", TOK_REFERENCED },
{ ".REFERENCED", TOK_REFERENCED }, { ".REFERENCED", TOK_REFERENCED },
{ ".RELOC", TOK_RELOC }, { ".RELOC", TOK_RELOC },

View File

@ -186,8 +186,10 @@ enum Token {
TOK_P816, TOK_P816,
TOK_PAGELENGTH, TOK_PAGELENGTH,
TOK_PARAMCOUNT, TOK_PARAMCOUNT,
TOK_PC02, TOK_PC02,
TOK_POPSEG,
TOK_PROC, TOK_PROC,
TOK_PUSHSEG,
TOK_REFERENCED, TOK_REFERENCED,
TOK_RELOC, TOK_RELOC,
TOK_REPEAT, TOK_REPEAT,