1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-26 20:29:34 +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",
"Lexical level was not terminated correctly",
"Segment attribute mismatch",
"Segment stack overflow",
"Segment stack is empty",
"Segment stack is not empty at end of assembly",
"CPU not supported",
"Counter underflow",
"Undefined label",

View File

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

View File

@ -621,6 +621,11 @@ int main (int argc, char* argv [])
/* Assemble the input */
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 (ErrorCount == 0) {
ULabCheck ();

View File

@ -70,36 +70,33 @@ unsigned long AbsPC = 0; /* PC if in absolute mode */
typedef struct Segment Segment;
struct Segment {
Segment* List; /* List of all segments */
Fragment* Root; /* Root of fragment list */
Fragment* Last; /* Pointer to last fragment */
unsigned char Align; /* Segment alignment */
unsigned char SegType; /* True if zero page segment */
Fragment* Root; /* Root of fragment list */
Fragment* Last; /* Pointer to last fragment */
unsigned Num; /* Segment number */
unsigned Align; /* Segment alignment */
unsigned long PC;
unsigned Num; /* Segment number */
char* Name; /* Segment name */
SegDef* Def; /* Segment definition (name and type) */
};
#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 */
static Segment NullSeg = {
0, 0, 0, 0, SEGTYPE_ABS, 0, 5, "NULL"
};
static Segment ZeropageSeg = {
&NullSeg, 0, 0, 0, SEGTYPE_ZP, 0, 4, "ZEROPAGE"
};
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"
};
static Segment NullSeg = SEG (&NullSegDef, 5, NULL);
static Segment ZeropageSeg = SEG (&ZeropageSegDef, 4, &NullSeg);
static Segment DataSeg = SEG (&DataSegDef, 3, &ZeropageSeg);
static Segment BssSeg = SEG (&BssSegDef, 2, &DataSeg);
static Segment RODataSeg = SEG (&RODataSegDef, 1, &BssSeg);
static Segment CodeSeg = SEG (&CodeSegDef, 0, &RODataSeg);
/* Number of segments */
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 */
{
Segment* S;
const char* N;
/* Check for too many segments */
if (SegmentCount >= 256) {
@ -131,30 +127,21 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
}
/* Check the segment name for invalid names */
N = Name;
if ((*N != '_' && !IsAlpha (*N)) || strlen (Name) > 80) {
if (!ValidSegName (Name)) {
Error (ERR_ILLEGAL_SEGMENT, Name);
}
do {
if (*N != '_' && !IsAlNum (*N)) {
Error (ERR_ILLEGAL_SEGMENT, Name);
break;
}
++N;
} while (*N);
/* Create a new segment */
S = xmalloc (sizeof (*S));
/* Initialize it */
S->List = 0;
S->Root = 0;
S->Last = 0;
S->Align = 0;
S->SegType = SegType;
S->PC = 0;
S->Num = SegmentCount++;
S->Name = xstrdup (Name);
S->List = 0;
S->Root = 0;
S->Last = 0;
S->Num = SegmentCount++;
S->Align = 0;
S->PC = 0;
S->Def = NewSegDef (Name, SegType);
/* Insert it into the segment list */
SegmentLast->List = S;
@ -166,65 +153,17 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
void UseCodeSeg (void)
/* 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)
void UseSeg (const SegDef* D)
/* Use the segment with the given name */
{
Segment* Seg = SegmentList;
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 */
if (SegType != SEGTYPE_DEFAULT && Seg->SegType != SegType) {
if (D->Type != SEGTYPE_DEFAULT && Seg->Def->Type != D->Type) {
Error (ERR_SEG_ATTR_MISMATCH);
/* Use the new attribute to avoid errors */
Seg->SegType = SegType;
Seg->Def->Type = D->Type;
}
ActiveSeg = Seg;
return;
@ -234,10 +173,11 @@ void UseSeg (const char* Name, unsigned SegType)
}
/* Segment is not in list, create a new one */
if (SegType == SEGTYPE_DEFAULT) {
SegType = SEGTYPE_ABS;
if (D->Type == SEGTYPE_DEFAULT) {
Seg = NewSegment (D->Name, SEGTYPE_ABS);
} else {
Seg = NewSegment (D->Name, D->Type);
}
Seg = NewSegment (Name, SegType);
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)
/* Get the number of the current segment */
{
@ -307,7 +255,7 @@ void SegAlign (unsigned Power, int Val)
int IsZPSeg (void)
/* 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)
/* 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 S->SegType;
return S->Def->Type;
}
@ -418,7 +366,7 @@ void SegDump (void)
unsigned I;
Fragment* F;
int State = -1;
printf ("New segment: %s", S->Name);
printf ("New segment: %s", S->Def->Name);
F = S->Root;
while (F) {
if (F->Type == FRAG_LITERAL) {
@ -461,10 +409,10 @@ static void WriteOneSeg (Segment* Seg)
unsigned LineInfoIndex;
/* Write the segment name followed by the byte count in this segment */
ObjWriteStr (Seg->Name);
ObjWriteStr (Seg->Def->Name);
ObjWrite32 (Seg->PC);
ObjWrite8 (Seg->Align);
ObjWrite8 (Seg->SegType);
ObjWrite8 (Seg->Def->Type);
/* Now walk through the fragment list for this segment and write the
* fragments.

View File

@ -55,6 +55,14 @@
/* Are we in absolute mode or in relocatable mode? */
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);
/* Use the code segment */
void UseSeg (const SegDef* D);
/* Use the given segment */
void UseRODataSeg (void);
/* Use the r/o data 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 */
const SegDef* GetCurrentSeg (void);
/* Get a pointer to the segment defininition of the current segment */
unsigned GetSegNum (void);
/* Get the number of the current segment */

View File

@ -42,7 +42,7 @@
/* common */
#include "bitops.h"
#include "cddefs.h"
#include "check.h"
#include "coll.h"
#include "symdefs.h"
#include "tgttrans.h"
@ -75,6 +75,10 @@
/* Keyword we're about to handle */
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)
/* Switch to the BSS segment */
{
UseBssSeg ();
UseSeg (&BssSegDef);
}
@ -407,7 +411,7 @@ static void DoCharMap (void)
static void DoCode (void)
/* Switch to the code segment */
{
UseCodeSeg ();
UseSeg (&CodeSegDef);
}
@ -485,7 +489,7 @@ static void DoConstructor (void)
static void DoData (void)
/* Switch to the data segment */
{
UseDataSeg ();
UseSeg (&DataSegDef);
}
@ -1059,7 +1063,7 @@ static void DoMacro (void)
static void DoNull (void)
/* 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)
/* 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)
/* Enter relocatable mode */
{
@ -1191,7 +1233,7 @@ static void DoRes (void)
static void DoROData (void)
/* Switch to the r/o data segment */
{
UseRODataSeg ();
UseSeg (&RODataSegDef);
}
@ -1205,7 +1247,7 @@ static void DoSegment (void)
"FAR", "LONG"
};
char Name [sizeof (SVal)];
int SegType;
SegDef Def = { Name, SEGTYPE_DEFAULT };
if (Tok != TOK_STRCON) {
ErrorSkip (ERR_STRCON_EXPECTED);
@ -1216,7 +1258,6 @@ static void DoSegment (void)
NextTok ();
/* Check for an optional segment attribute */
SegType = SEGTYPE_DEFAULT;
if (Tok == TOK_COMMA) {
NextTok ();
if (Tok != TOK_IDENT) {
@ -1228,18 +1269,18 @@ static void DoSegment (void)
case 0:
case 1:
/* Zeropage */
SegType = SEGTYPE_ZP;
Def.Type = SEGTYPE_ZP;
break;
case 2:
/* Absolute */
SegType = SEGTYPE_ABS;
Def.Type = SEGTYPE_ABS;
break;
case 3:
case 4:
/* Far */
SegType = SEGTYPE_FAR;
Def.Type = SEGTYPE_FAR;
break;
default:
@ -1250,7 +1291,7 @@ static void DoSegment (void)
}
/* Set the segment */
UseSeg (Name, SegType);
UseSeg (&Def);
}
}
@ -1312,7 +1353,7 @@ static void DoWord (void)
static void DoZeropage (void)
/* Switch to the zeropage segment */
{
UseZeropageSeg ();
UseSeg (&ZeropageSegDef);
}
@ -1416,7 +1457,9 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoPageLength },
{ ccNone, DoUnexpected }, /* .PARAMCOUNT */
{ ccNone, DoPC02 },
{ ccNone, DoPopSeg },
{ ccNone, DoProc },
{ ccNone, DoPushSeg },
{ ccNone, DoUnexpected }, /* .REFERENCED */
{ ccNone, DoReloc },
{ 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 */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 1998-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -64,6 +64,9 @@ int TokIsPseudo (unsigned Tok);
void HandlePseudo (void);
/* Handle a pseudo instruction */
void SegStackCheck (void);
/* Check if the segment stack is empty at end of assembly */
/* End of pseudo.h */

View File

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

View File

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