From: cuz Date: Fri, 7 Nov 2003 19:28:37 +0000 (+0000) Subject: Working on better 65816 support X-Git-Tag: V2.12.0~1180 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=7e740788015cdb2c817d51fffa7c60e5a9d49646;p=cc65 Working on better 65816 support git-svn-id: svn://svn.cc65.org/cc65/trunk@2619 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/ca65/error.c b/src/ca65/error.c index ce5212638..9324c022f 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -51,7 +51,7 @@ /* Warning level */ -unsigned WarnLevel = 1; +unsigned WarnLevel = 1; /* Statistics */ unsigned ErrorCount = 0; @@ -72,11 +72,13 @@ void WarningMsg (const FilePos* Pos, unsigned WarnNum, va_list ap) unsigned char Level; const char* Msg; } Warnings [WARN_COUNT-1] = { - { 2, "Symbol `%s' is defined but never used" }, - { 2, "Symbol `%s' is imported but never used" }, - { 1, "Cannot track processor status byte" }, - { 1, "Suspicious address expression" }, - { 0, "User warning: %s" }, + { 2, "Symbol `%s' is defined but never used" }, + { 2, "Symbol `%s' is imported but never used" }, + { 1, "Cannot track processor status byte" }, + { 1, "Suspicious address expression" }, + { 0, "Unnamed .PROCs are deprecated, please use .SCOPE" }, + { 1, "Address size mismatch for symbol `%s'" }, + { 0, "User warning: %s" }, }; if (Warnings [WarnNum-1].Level <= WarnLevel) { @@ -149,6 +151,7 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap) "`.ENDMACRO' expected", "Option key expected", "`=' expected", + "Address size specifier expected", "Command is only valid in 65816 mode", "User error: %s", "String constant too long", @@ -158,7 +161,6 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap) "Illegal character to start local symbols", "Illegal use of local symbol", "Illegal segment name: `%s'", - "Illegal segment attribute", "Illegal macro package name", "Illegal emulation feature", "Illegal scope specifier", @@ -180,6 +182,7 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap) "Macro parameter expected", "Circular reference in symbol definition", "Symbol `%s' redeclaration mismatch", + "Address size mismatch for symbol `%s'", "Alignment value must be a power of 2", "Duplicate `.ELSE'", "Conditional assembly branch was never closed", diff --git a/src/ca65/error.h b/src/ca65/error.h index 8809166c3..f376344d0 100644 --- a/src/ca65/error.h +++ b/src/ca65/error.h @@ -57,6 +57,8 @@ enum Warnings { WARN_IMPORT_NOT_REFERENCED, WARN_CANNOT_TRACK_STATUS, WARN_SUSPICIOUS_ADDREXPR, + WARN_UNNAMED_PROC, + WARN_ADDR_SIZE_MISMATCH, WARN_USER, WARN_COUNT /* Warning count */ }; @@ -64,7 +66,7 @@ enum Warnings { /* Error numbers */ enum Errors { ERR_NONE, /* No error */ - ERR_NOT_IMPLEMENTED, /* Command/operation not implemented */ + ERR_NOT_IMPLEMENTED, /* Command/operation not implemented */ ERR_CANNOT_OPEN_INCLUDE, ERR_CANNOT_READ_INCLUDE, ERR_INCLUDE_NESTING, @@ -91,6 +93,7 @@ enum Errors { ERR_ENDMACRO_EXPECTED, ERR_OPTION_KEY_EXPECTED, ERR_EQ_EXPECTED, + ERR_ADDR_SIZE_EXPECTED, ERR_816_MODE_ONLY, ERR_USER, ERR_STRING_TOO_LONG, @@ -99,8 +102,7 @@ enum Errors { ERR_ILLEGAL_ADDR_MODE, ERR_ILLEGAL_LOCALSTART, ERR_ILLEGAL_LOCAL_USE, - ERR_ILLEGAL_SEGMENT, - ERR_ILLEGAL_SEG_ATTR, + ERR_ILLEGAL_SEGMENT, ERR_ILLEGAL_MACPACK, ERR_ILLEGAL_FEATURE, ERR_ILLEGAL_SCOPE, @@ -122,6 +124,7 @@ enum Errors { ERR_MACRO_PARAM_EXPECTED, ERR_CIRCULAR_REFERENCE, ERR_SYM_REDECL_MISMATCH, + ERR_ADDR_SIZE_MISMATCH, ERR_ALIGN, ERR_DUPLICATE_ELSE, ERR_OPEN_IF, @@ -156,7 +159,7 @@ enum Fatals { FAT_NESTING, FAT_IF_NESTING, FAT_TOO_MANY_SYMBOLS, - FAT_COUNT /* Fatal error count */ + FAT_COUNT /* Fatal error count */ }; diff --git a/src/ca65/expr.c b/src/ca65/expr.c index f72f12eee..02ae88a36 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -917,7 +917,7 @@ ExprNode* GenCurrentPC (void) if (RelocMode) { /* Create SegmentBase + Offset */ Root = NewExprNode (EXPR_PLUS); - Root->Left = GenSectionExpr (GetSegNum ()); + Root->Left = GenSectionExpr (GetCurrentSegNum ()); Root->Right = GenLiteralExpr (GetPC ()); } else { /* Absolute mode, just return PC value */ @@ -950,7 +950,7 @@ ExprNode* GenBranchExpr (unsigned Offs) /* Create *+Offs */ if (RelocMode) { N = NewExprNode (EXPR_PLUS); - N->Left = GenSectionExpr (GetSegNum ()); + N->Left = GenSectionExpr (GetCurrentSegNum ()); N->Right = GenLiteralExpr (GetPC () + Offs); } else { N = GenLiteralExpr (GetPC () + Offs); @@ -1120,7 +1120,7 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte) break; case EXPR_SECTION: - if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) { + if (GetSegAddrSize (N->V.SegNum) == ADDR_SIZE_ZP) { *IsByte = 1; } break; diff --git a/src/ca65/main.c b/src/ca65/main.c index fd93fac97..1bec12ba2 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -39,6 +39,7 @@ #include /* common */ +#include "addrsize.h" #include "chartype.h" #include "cmdline.h" #include "print.h" @@ -188,7 +189,7 @@ static void DefineSymbol (const char* Def) } /* Mark the symbol as defined */ - SymDef (Sym, GenLiteralExpr (Val), SYM_DEFAULT); + SymDef (Sym, GenLiteralExpr (Val), ADDR_SIZE_DEFAULT, SF_NONE); } @@ -381,18 +382,16 @@ static void OneLine (void) */ if (Tok == TOK_EQ || Tok == TOK_ASSIGN) { /* If it's an assign token, we have a label */ - unsigned Flags = (Tok == TOK_ASSIGN)? SYM_LABEL : SYM_DEFAULT; + unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE; /* Skip the '=' */ NextTok (); /* Define the symbol with the expression following the '=' */ - SymDef (Sym, Expression(), Flags); + SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); /* Don't allow anything after a symbol definition */ Done = 1; } else { - /* Define the symbol flags */ - unsigned Flags = IsZPSeg ()? SYM_ZP | SYM_LABEL : SYM_LABEL; /* Define a label */ - SymDef (Sym, GenCurrentPC (), Flags); + SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); /* Skip the colon. If NoColonLabels is enabled, allow labels * without a colon if there is no whitespace before the * identifier. @@ -525,7 +524,7 @@ int main (int argc, char* argv []) /* Enter the base lexical level. We must do that here, since we may * define symbols using -D. */ - SymEnterLevel (""); + SymEnterLevel ("", ADDR_SIZE_DEFAULT); /* Check the parameters */ I = 1; diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 1a98e855d..8e9ac1d90 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -114,6 +114,22 @@ static void DoInvalid (void); +static unsigned OptionalAddrSize (void) +/* If a colon follows, parse an optional address size spec and return it. + * Otherwise return ADDR_SIZE_DEFAULT. + */ +{ + unsigned AddrSize = ADDR_SIZE_DEFAULT; + if (Tok == TOK_COLON) { + NextTok (); + AddrSize = ParseAddrSize (); + NextTok (); + } + return AddrSize; +} + + + static void SetBoolOption (unsigned char* Flag) /* Read a on/off/+/- option and set flag accordingly */ { @@ -145,16 +161,37 @@ static void SetBoolOption (unsigned char* Flag) -static void ExportImport (void (*SymFunc) (const char*)) +static void ExportImport (void (*Func) (SymEntry*, unsigned, unsigned), + unsigned DefAddrSize, unsigned Flags) /* Export or import symbols */ { + SymEntry* Sym; + unsigned AddrSize; + while (1) { + + /* We need an identifier here */ if (Tok != TOK_IDENT) { ErrorSkip (ERR_IDENT_EXPECTED); - break; + return; } - SymFunc (SVal); - NextTok (); + + /* Find the symbol table entry, allocate a new one if necessary */ + Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW); + + /* Skip the name */ + NextTok (); + + /* Get an optional address size */ + AddrSize = OptionalAddrSize (); + if (AddrSize == ADDR_SIZE_DEFAULT) { + AddrSize = DefAddrSize; + } + + /* Call the actual import/export function */ + Func (Sym, AddrSize, Flags); + + /* More symbols? */ if (Tok == TOK_COMMA) { NextTok (); } else { @@ -366,7 +403,7 @@ static void DoAssert (void) break; default: - Error (ERR_ILLEGAL_SEG_ATTR); + Error (ERR_ILLEGAL_ASSERT_ACTION); } NextTok (); ConsumeComma (); @@ -702,7 +739,7 @@ static void DoExitMacro (void) static void DoExport (void) /* Export a symbol */ { - ExportImport (SymExport); + ExportImport (SymExport, ADDR_SIZE_DEFAULT, SF_NONE); } @@ -710,7 +747,7 @@ static void DoExport (void) static void DoExportZP (void) /* Export a zeropage symbol */ { - ExportImport (SymExportZP); + ExportImport (SymExport, ADDR_SIZE_ZP, SF_NONE); } @@ -856,7 +893,7 @@ static void DoFileOpt (void) static void DoForceImport (void) /* Do a forced import on a symbol */ { - ExportImport (SymImportForced); + ExportImport (SymImport, ADDR_SIZE_DEFAULT, SF_FORCED); } @@ -864,7 +901,7 @@ static void DoForceImport (void) static void DoGlobal (void) /* Declare a global symbol */ { - ExportImport (SymGlobal); + ExportImport (SymGlobal, ADDR_SIZE_DEFAULT, SF_NONE); } @@ -872,7 +909,7 @@ static void DoGlobal (void) static void DoGlobalZP (void) /* Declare a global zeropage symbol */ { - ExportImport (SymGlobalZP); + ExportImport (SymGlobal, ADDR_SIZE_ZP, SF_NONE); } @@ -906,7 +943,7 @@ static void DoI8 (void) static void DoImport (void) /* Import a symbol */ { - ExportImport (SymImport); + ExportImport (SymImport, ADDR_SIZE_DEFAULT, SF_NONE); } @@ -914,7 +951,7 @@ static void DoImport (void) static void DoImportZP (void) /* Import a zero page symbol */ { - ExportImport (SymImportZP); + ExportImport (SymImport, ADDR_SIZE_ZP, SF_NONE); } @@ -1244,18 +1281,35 @@ static void DoProc (void) /* Start a new lexical scope */ { if (Tok == TOK_IDENT) { - /* The new scope has a name */ - SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW); - unsigned Flags = SYM_LABEL; - if (IsZPSeg ()) { - Flags |= SYM_ZP; - } - SymDef (Sym, GenCurrentPC (), Flags); - SymEnterLevel (SVal); - NextTok (); + + unsigned AddrSize; + + /* The new scope has a name. Remember it. */ + char Name[sizeof(SVal)]; + strcpy (Name, SVal); + + /* Search for the symbol, generate a new one if needed */ + SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW); + + /* Skip the scope name */ + NextTok (); + + /* Read an optional address size specifier */ + AddrSize = OptionalAddrSize (); + + /* Mark the symbol as defined */ + SymDef (Sym, GenCurrentPC (), AddrSize, SF_LABEL); + + /* Enter a new scope with the given name */ + SymEnterLevel (Name, AddrSize); + } else { + + /* A .PROC statement without a name */ char Buf[sizeof (SVal)]; - SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope")); + SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"), ADDR_SIZE_DEFAULT); + Warning (WARN_UNNAMED_PROC); + } } @@ -1279,7 +1333,7 @@ static void DoPushSeg (void) } /* Get the current segment and push it */ - CollAppend (&SegStack, DupSegDef (GetCurrentSeg ())); + CollAppend (&SegStack, DupSegDef (GetCurrentSegDef ())); } @@ -1344,15 +1398,9 @@ static void DoROData (void) static void DoSegment (void) /* Switch to another segment */ { - static const char* AttrTab [] = { - "ZEROPAGE", "DIRECT", - "ABSOLUTE", - "FAR", "LONG" - }; char Name [sizeof (SVal)]; SegDef Def; Def.Name = Name; - Def.Type = SEGTYPE_DEFAULT; if (Tok != TOK_STRCON) { ErrorSkip (ERR_STRCON_EXPECTED); @@ -1362,38 +1410,8 @@ static void DoSegment (void) strcpy (Name, SVal); NextTok (); - /* Check for an optional segment attribute */ - if (Tok == TOK_COMMA) { - NextTok (); - if (Tok != TOK_IDENT) { - ErrorSkip (ERR_IDENT_EXPECTED); - } else { - int Attr = GetSubKey (AttrTab, sizeof (AttrTab) / sizeof (AttrTab [0])); - switch (Attr) { - - case 0: - case 1: - /* Zeropage */ - Def.Type = SEGTYPE_ZP; - break; - - case 2: - /* Absolute */ - Def.Type = SEGTYPE_ABS; - break; - - case 3: - case 4: - /* Far */ - Def.Type = SEGTYPE_FAR; - break; - - default: - Error (ERR_ILLEGAL_SEG_ATTR); - } - NextTok (); - } - } + /* Check for an optional address size modifier */ + Def.AddrSize = OptionalAddrSize (); /* Set the segment */ UseSeg (&Def); diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 7ac09acdf..8bad4f6c2 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -42,6 +42,7 @@ #include /* common */ +#include "addrsize.h" #include "chartype.h" #include "check.h" #include "fname.h" @@ -1135,6 +1136,41 @@ int GetSubKey (const char** Keys, unsigned Count) +unsigned ParseAddrSize (void) +/* Check if the next token is a keyword that denotes an address size specifier. + * If so, return the corresponding address size constant, otherwise output an + * error message and return ADDR_SIZE_DEFAULT. + */ +{ + static const char* Keys[] = { + "DIRECT", "ZEROPAGE", "ZP", + "ABSOLUTE", "ABS", "NEAR", + "FAR", + }; + + /* Check for an identifier */ + if (Tok != TOK_IDENT) { + Error (ERR_ADDR_SIZE_EXPECTED); + return ADDR_SIZE_DEFAULT; + } + + /* Search for the attribute */ + switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) { + case 0: + case 1: + case 2: return ADDR_SIZE_FAR; + case 3: + case 4: + case 5: return ADDR_SIZE_ABS; + case 6: return ADDR_SIZE_FAR; + default: + Error (ERR_ADDR_SIZE_EXPECTED); + return ADDR_SIZE_DEFAULT; + } +} + + + void InitScanner (const char* InFile) /* Initialize the scanner, open the given input file */ { diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index f65ecde76..4b2d0ef39 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -291,6 +291,12 @@ int GetSubKey (const char** Keys, unsigned Count); * or -1 if the keyword was not found. */ +unsigned ParseAddrSize (void); +/* Check if the next token is a keyword that denotes an address size specifier. + * If so, return the corresponding address size constant, otherwise output an + * error message and return ADDR_SIZE_DEFAULT. + */ + void InitScanner (const char* InFile); /* Initialize the scanner, open the given input file */ diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 8fd5e356f..3b760136c 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -64,31 +64,17 @@ int RelocMode = 1; 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 long FragCount; /* Number of fragments */ - unsigned Num; /* Segment number */ - unsigned Align; /* Segment alignment */ - unsigned long PC; - SegDef* Def; /* Segment definition (name and type) */ -}; - - +/* Segment initializer macro */ #define SEG(segdef, num, prev) \ { prev, 0, 0, 0, num, 0, 0, segdef } /* Definitions for predefined segments */ -SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL, SEGTYPE_ABS); -SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, SEGTYPE_ZP); -SegDef DataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_DATA, SEGTYPE_ABS); -SegDef BssSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_BSS, SEGTYPE_ABS); -SegDef RODataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA, SEGTYPE_ABS); -SegDef CodeSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE, SEGTYPE_ABS); +SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL, ADDR_SIZE_ABS); +SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, ADDR_SIZE_ZP); +SegDef DataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_DATA, ADDR_SIZE_ABS); +SegDef BssSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_BSS, ADDR_SIZE_ABS); +SegDef RODataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA, ADDR_SIZE_ABS); +SegDef CodeSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE, ADDR_SIZE_ABS); /* Predefined segments */ static Segment NullSeg = SEG (&NullSegDef, 5, NULL); @@ -106,7 +92,7 @@ static Segment* SegmentList = &CodeSeg; static Segment* SegmentLast = &NullSeg; /* Currently active segment */ -static Segment* ActiveSeg = &CodeSeg; +Segment* ActiveSeg = &CodeSeg; @@ -116,7 +102,7 @@ static Segment* ActiveSeg = &CodeSeg; -static Segment* NewSegment (const char* Name, unsigned SegType) +static Segment* NewSegment (const char* Name, unsigned AddrSize) /* Create a new segment, insert it into the global list and return it */ { Segment* S; @@ -142,7 +128,7 @@ static Segment* NewSegment (const char* Name, unsigned SegType) S->Num = SegmentCount++; S->Align = 0; S->PC = 0; - S->Def = NewSegDef (Name, SegType); + S->Def = NewSegDef (Name, AddrSize); /* Insert it into the segment list */ SegmentLast->List = S; @@ -198,10 +184,11 @@ void UseSeg (const SegDef* D) while (Seg) { if (strcmp (Seg->Def->Name, D->Name) == 0) { /* We found this segment. Check if the type is identical */ - if (D->Type != SEGTYPE_DEFAULT && Seg->Def->Type != D->Type) { + if (D->AddrSize != ADDR_SIZE_DEFAULT && + Seg->Def->AddrSize != D->AddrSize) { Error (ERR_SEG_ATTR_MISMATCH); /* Use the new attribute to avoid errors */ - Seg->Def->Type = D->Type; + Seg->Def->AddrSize = D->AddrSize; } ActiveSeg = Seg; return; @@ -211,10 +198,10 @@ void UseSeg (const SegDef* D) } /* Segment is not in list, create a new one */ - if (D->Type == SEGTYPE_DEFAULT) { - Seg = NewSegment (D->Name, SEGTYPE_ABS); + if (D->AddrSize == ADDR_SIZE_DEFAULT) { + Seg = NewSegment (D->Name, ADDR_SIZE_ABS); } else { - Seg = NewSegment (D->Name, D->Type); + Seg = NewSegment (D->Name, D->AddrSize); } ActiveSeg = Seg; } @@ -238,22 +225,6 @@ 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 */ -{ - return ActiveSeg->Num; -} - - - void SegAlign (unsigned Power, int Val) /* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the * actual fill value will be determined by the linker), otherwise use the @@ -290,24 +261,8 @@ void SegAlign (unsigned Power, int Val) -int IsZPSeg (void) -/* Return true if the current segment is a zeropage segment */ -{ - return (ActiveSeg->Def->Type == SEGTYPE_ZP); -} - - - -int IsFarSeg (void) -/* Return true if the current segment is a far segment */ -{ - return (ActiveSeg->Def->Type == SEGTYPE_FAR); -} - - - -unsigned GetSegType (unsigned SegNum) -/* Return the type of the segment with the given number */ +unsigned GetSegAddrSize (unsigned SegNum) +/* Return the address size of the segment with the given number */ { /* Search for the segment */ Segment* S = SegmentList; @@ -321,8 +276,8 @@ unsigned GetSegType (unsigned SegNum) FAIL ("Invalid segment number"); } - /* Return the segment type */ - return S->Def->Type; + /* Return the address size */ + return S->Def->AddrSize; } @@ -461,7 +416,7 @@ static void WriteOneSeg (Segment* Seg) ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */ ObjWrite32 (Seg->PC); /* Size */ ObjWrite8 (Seg->Align); /* Segment alignment */ - ObjWrite8 (Seg->Def->Type); /* Type of the segment */ + ObjWrite8 (Seg->Def->AddrSize); /* Address size of the segment */ ObjWriteVar (Seg->FragCount); /* Number of fragments */ /* Now walk through the fragment list for this segment and write the diff --git a/src/ca65/segment.h b/src/ca65/segment.h index 1d6ce796e..85f50308b 100644 --- a/src/ca65/segment.h +++ b/src/ca65/segment.h @@ -40,6 +40,7 @@ /* common */ #include "fragdefs.h" +#include "inline.h" #include "segdefs.h" /* ca65 */ @@ -48,13 +49,26 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ +/* Segment definition */ +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 long FragCount; /* Number of fragments */ + unsigned Num; /* Segment number */ + unsigned Align; /* Segment alignment */ + unsigned long PC; + SegDef* Def; /* Segment definition (name and type) */ +}; + /* Are we in absolute mode or in relocatable mode? */ -extern int RelocMode; +extern int RelocMode; /* Definitions for predefined segments */ extern SegDef NullSegDef; @@ -64,6 +78,9 @@ extern SegDef BssSegDef; extern SegDef RODataSegDef; extern SegDef CodeSegDef; +/* Currently active segment */ +extern Segment* ActiveSeg; + /*****************************************************************************/ @@ -78,11 +95,35 @@ Fragment* GenFragment (unsigned char Type, unsigned short Len); void UseSeg (const SegDef* D); /* Use the given segment */ -const SegDef* GetCurrentSeg (void); +#if defined(HAVE_INLINE) +INLINE const SegDef* GetCurrentSegDef (void) /* Get a pointer to the segment defininition of the current segment */ +{ + return ActiveSeg->Def; +} +#else +# define GetCurrentSegDef() (ActiveSeg->Def) +#endif -unsigned GetSegNum (void); +#if defined(HAVE_INLINE) +INLINE unsigned GetCurrentSegNum (void) /* Get the number of the current segment */ +{ + return ActiveSeg->Num; +} +#else +# define GetCurrentSegNum() (ActiveSeg->Num) +#endif + +#if defined(HAVE_INLINE) +INLINE unsigned GetCurrentSegAddrSize (void) +/* Get the address size of the current segment */ +{ + return ActiveSeg->Def->AddrSize; +} +#else +# define GetCurrentSegAddrSize() (ActiveSeg->Def->AddrSize) +#endif void SegAlign (unsigned Power, int Val); /* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the @@ -90,14 +131,8 @@ void SegAlign (unsigned Power, int Val); * given value. */ -int IsZPSeg (void); -/* Return true if the current segment is a zeropage segment */ - -int IsFarSeg (void); -/* Return true if the current segment is a far segment */ - -unsigned GetSegType (unsigned SegNum); -/* Return the type of the segment with the given number */ +unsigned GetSegAddrSize (unsigned SegNum); +/* Return the address size of the segment with the given number */ unsigned long GetPC (void); /* Get the program counter of the current segment */ diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 660fdf0df..fd9f195fb 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -1,6 +1,6 @@ /*****************************************************************************/ /* */ -/* symentry.c */ +/* symentry.c */ /* */ /* Symbol table entry forward for the ca65 macroassembler */ /* */ @@ -36,6 +36,7 @@ #include /* common */ +#include "addrsize.h" #include "xmalloc.h" /* ca65 */ @@ -63,7 +64,7 @@ SymEntry* SymLast = 0; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -84,6 +85,20 @@ int IsLocalNameId (unsigned Name) +static unsigned SymAddrSize (const SymEntry* S) +/* Get the default address size for a symbol. */ +{ + /* Local symbols are always near (is this ok?) */ + if (IsLocalNameId (S->Name)) { + return ADDR_SIZE_ABS; + } + + /* Return the address size of the enclosing scope */ + return S->SymTab->AddrSize; +} + + + SymEntry* NewSymEntry (const char* Name) /* Allocate a symbol table entry, initialize and return it */ { @@ -91,16 +106,18 @@ SymEntry* NewSymEntry (const char* Name) SymEntry* S = xmalloc (sizeof (SymEntry)); /* Initialize the entry */ - S->Left = 0; - S->Right = 0; - S->Locals = 0; - S->SymTab = 0; - S->Pos = CurPos; - S->Flags = 0; - S->V.Expr = 0; - S->ExprRefs = AUTO_COLLECTION_INITIALIZER; + S->Left = 0; + S->Right = 0; + S->Locals = 0; + S->SymTab = 0; + S->Pos = CurPos; + S->Flags = 0; + S->V.Expr = 0; + S->ExprRefs = AUTO_COLLECTION_INITIALIZER; + S->ExportSize = ADDR_SIZE_DEFAULT; + S->AddrSize = ADDR_SIZE_DEFAULT; memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio)); - S->Name = GetStringId (Name); + S->Name = GetStringId (Name); /* Insert it into the list of all entries */ S->List = SymList; @@ -121,7 +138,7 @@ void SymRef (SymEntry* S) -void SymDef (SymEntry* S, ExprNode* Expr, unsigned Flags) +void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags) /* Define a new symbol */ { if (S->Flags & SF_IMPORT) { @@ -136,7 +153,12 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned Flags) return; } - /* Set the symbol data */ + /* Map a default address size to a real value */ + if (AddrSize == ADDR_SIZE_DEFAULT) { + AddrSize = SymAddrSize (S); + } + + /* Set the symbol value */ if (IsConstExpr (Expr)) { /* Expression is const, store the value */ S->Flags |= SF_CONST; @@ -146,16 +168,26 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned Flags) /* Not const, store the expression */ S->V.Expr = Expr; } - S->Flags |= SF_DEFINED; - if (Flags & SYM_ZP) { - S->Flags |= SF_ZP; + + /* If the symbol is marked as global, export it */ + if (S->Flags & SF_GLOBAL) { + S->ExportSize = S->AddrSize; + S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT; } - if (Flags & SYM_LABEL) { - S->Flags |= SF_LABEL; + + /* Mark the symbol as defined and use the given address size */ + S->Flags |= (SF_DEFINED | Flags); + S->AddrSize = AddrSize; + + /* If the symbol is exported, check the address sizes */ + if (S->Flags & SF_EXPORT) { + if (S->AddrSize > S->ExportSize) { + Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S)); + } } /* If the symbol is a ZP symbol, check if the value is in correct range */ - if (S->Flags & SF_ZP) { + if (S->AddrSize == ADDR_SIZE_ZP) { /* Already marked as ZP symbol by some means */ if (!IsByteExpr (Expr)) { Error (ERR_RANGE); @@ -170,6 +202,147 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned Flags) +void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags) +/* Mark the given symbol as an imported symbol */ +{ + /* Don't accept local symbols */ + if (IsLocalNameId (S->Name)) { + Error (ERR_ILLEGAL_LOCAL_USE); + return; + } + + if (S->Flags & SF_DEFINED) { + Error (ERR_SYM_ALREADY_DEFINED, GetSymName (S)); + S->Flags |= SF_MULTDEF; + return; + } + if (S->Flags & SF_EXPORT) { + /* The symbol is already marked as exported symbol */ + Error (ERR_SYM_ALREADY_EXPORT, GetSymName (S)); + return; + } + + /* Map a default address size to a real value */ + if (AddrSize == ADDR_SIZE_DEFAULT) { + AddrSize = SymAddrSize (S); + } + + /* If the symbol is marked as import or global, check the symbol flags, + * then do silently remove the global flag + */ + if (S->Flags & (SF_IMPORT | SF_GLOBAL)) { + if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) || + AddrSize != S->AddrSize) { + Error (ERR_SYM_REDECL_MISMATCH, GetSymName (S)); + } + S->Flags &= ~SF_GLOBAL; + } + + /* Set the symbol data */ + S->Flags |= (SF_IMPORT | Flags); + S->AddrSize = AddrSize; +} + + + +void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags) +/* Mark the given symbol as an exported symbol */ +{ + /* Don't accept local symbols */ + if (IsLocalNameId (S->Name)) { + Error (ERR_ILLEGAL_LOCAL_USE); + return; + } + + /* Check if it's ok to export the symbol */ + if (S->Flags & SF_IMPORT) { + /* The symbol is already marked as imported external symbol */ + Error (ERR_SYM_ALREADY_IMPORT, GetSymName (S)); + return; + } + + /* Map a default address size to a real value */ + if (AddrSize == ADDR_SIZE_DEFAULT) { + AddrSize = SymAddrSize (S); + } + + /* If the symbol was already marked as an export or global, check if + * this was done specifiying the same address size. In case of a global + * declaration, silently remove the global flag. + */ + if (S->Flags & (SF_EXPORT | SF_GLOBAL)) { + if (S->ExportSize != AddrSize) { + Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S)); + } + S->Flags &= ~SF_GLOBAL; + } + S->ExportSize = AddrSize; + + /* If the symbol is already defined, check symbol size against the + * exported size. + */ + if (S->Flags & SF_DEFINED) { + if (S->AddrSize > S->ExportSize) { + Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S)); + } + } + + /* Set the symbol data */ + S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags); +} + + + +void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags) +/* Mark the given symbol as a global symbol, that is, as a symbol that is + * either imported or exported. + */ +{ + /* Don't accept local symbols */ + if (IsLocalNameId (S->Name)) { + Error (ERR_ILLEGAL_LOCAL_USE); + return; + } + + /* Map a default address size to a real value */ + if (AddrSize == ADDR_SIZE_DEFAULT) { + AddrSize = SymAddrSize (S); + } + + /* If the symbol is already marked as import or export, check the + * size of the definition, then bail out. + */ + if (S->Flags & SF_IMPORT) { + if (AddrSize != S->AddrSize) { + Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S)); + } + return; + } + if (S->Flags & SF_EXPORT) { + if (AddrSize != S->ExportSize) { + Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S)); + } + return; + } + + /* If the symbol is already defined, export it. Otherwise mark it as + * global. + */ + if (S->Flags & SF_DEFINED) { + /* The symbol is defined, export it */ + if (S->ExportSize != AddrSize) { + Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S)); + } + S->Flags |= (SF_EXPORT | Flags); + S->ExportSize = AddrSize; + } else { + S->Flags |= (SF_GLOBAL | Flags); + S->AddrSize = AddrSize; + } +} + + + int SymIsDef (const SymEntry* S) /* Return true if the given symbol is already defined */ { diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index 5d5aadd0a..54ce40cf6 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -69,11 +69,6 @@ #define SF_DEFINED 0x4000 /* Defined */ #define SF_REFERENCED 0x8000 /* Referenced */ -/* Flags used in SymDef */ -#define SYM_DEFAULT 0x00 -#define SYM_ZP 0x01 -#define SYM_LABEL 0x02 - /* Arguments for SymFind... */ #define SYM_FIND_EXISTING 0 #define SYM_ALLOC_NEW 1 @@ -95,6 +90,8 @@ struct SymEntry { SymEntry* Sym; /* Symbol (if trampoline entry) */ } V; Collection ExprRefs; /* Expressions using this symbol */ + unsigned char ExportSize; /* Export address size */ + unsigned char AddrSize; /* Address size of label */ unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */ /* ...actually value+1 (used as flag) */ unsigned Name; /* Name index in global string pool */ @@ -143,12 +140,23 @@ INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr) #define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr) #endif -void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned Flags); +void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned AddrSize, unsigned Flags); /* Mark a symbol as defined */ void SymRef (SymEntry* Sym); /* Mark the given symbol as referenced */ +void SymImport (SymEntry* Sym, unsigned AddrSize, unsigned Flags); +/* Mark the given symbol as an imported symbol */ + +void SymExport (SymEntry* Sym, unsigned AddrSize, unsigned Flags); +/* Mark the given symbol as an exported symbol */ + +void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags); +/* Mark the given symbol as a global symbol, that is, as a symbol that is + * either imported or exported. + */ + int SymIsDef (const SymEntry* Sym); /* Return true if the given symbol is already defined */ diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index 70945c34f..52d148037 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -36,6 +36,7 @@ #include /* common */ +#include "addrsize.h" #include "check.h" #include "hashstr.h" #include "symdefs.h" @@ -82,7 +83,7 @@ static unsigned ExportCount = 0;/* Counter for export symbols */ -static unsigned SymTableSize (unsigned Level) +static unsigned ScopeTableSize (unsigned Level) /* Get the size of a table for the given lexical level */ { switch (Level) { @@ -94,12 +95,12 @@ static unsigned SymTableSize (unsigned Level) -static SymTable* NewSymTable (SymTable* Parent, const char* Name) +static SymTable* NewSymTable (SymTable* Parent, unsigned AddrSize, const char* Name) /* Allocate a symbol table on the heap and return it */ { /* Determine the lexical level and the number of table slots */ unsigned Level = Parent? Parent->Level + 1 : 0; - unsigned Slots = SymTableSize (Level); + unsigned Slots = ScopeTableSize (Level); /* Allocate memory */ SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*)); @@ -108,6 +109,8 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name) S->Left = 0; S->Right = 0; S->Childs = 0; + S->AddrSize = AddrSize; + S->Type = 0; S->Level = Level; S->TableSlots = Slots; S->TableEntries = 0; @@ -201,11 +204,17 @@ static int SearchSymTree (SymEntry* T, const char* Name, SymEntry** E) -void SymEnterLevel (const char* ScopeName) +void SymEnterLevel (const char* ScopeName, unsigned AddrSize) /* Enter a new lexical level */ { /* ### Check existing scope */ + /* Map a default address size to something real */ + if (AddrSize == ADDR_SIZE_DEFAULT) { + /* Use the segment address size */ + AddrSize = GetCurrentSegAddrSize (); + } + /* Create the new table */ CurrentScope = NewSymTable (CurrentScope, ScopeName); } @@ -220,7 +229,7 @@ void SymLeaveLevel (void) -SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags) +SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew) /* Find a scope in the given enclosing scope */ { SymTable** T = &Parent->Childs; @@ -237,7 +246,7 @@ SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags) } /* Create a new scope if requested and we didn't find one */ - if (*T == 0 && Flags == SYM_ALLOC_NEW) { + if (*T == 0 && AllocNew) { *T = NewSymTable (Parent, Name); } @@ -359,172 +368,6 @@ static SymEntry* SymFindAny (SymTable* Scope, const char* Name) -static void SymImportInternal (const char* Name, unsigned Flags) -/* Mark the given symbol as an imported symbol */ -{ - SymEntry* S; - - /* Don't accept local symbols */ - if (IsLocalName (Name)) { - Error (ERR_ILLEGAL_LOCAL_USE); - return; - } - - /* Do we have such a symbol? */ - S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW); - if (S->Flags & SF_DEFINED) { - Error (ERR_SYM_ALREADY_DEFINED, Name); - S->Flags |= SF_MULTDEF; - return; - } - if (S->Flags & SF_EXPORT) { - /* The symbol is already marked as exported symbol */ - Error (ERR_SYM_ALREADY_EXPORT, Name); - return; - } - - /* If the symbol is marked as global, check the symbol flags, then do - * silently remove the global flag - */ - if (S->Flags & SF_GLOBAL) { - if ((Flags & (SF_ZP | SF_FORCED)) != (S->Flags & (SF_ZP | SF_FORCED))) { - Error (ERR_SYM_REDECL_MISMATCH, Name); - } - S->Flags &= ~SF_GLOBAL; - } - - /* Set the symbol data */ - S->Flags |= (SF_IMPORT | Flags); -} - - - -void SymImport (const char* Name) -/* Mark the given symbol as an imported symbol */ -{ - SymImportInternal (Name, SF_NONE); -} - - - -void SymImportZP (const char* Name) -/* Mark the given symbol as a forced imported symbol */ -{ - SymImportInternal (Name, SF_ZP); -} - - - -void SymImportForced (const char* Name) -/* Mark the given symbol as a forced imported symbol */ -{ - SymImportInternal (Name, SF_FORCED); -} - - - -static void SymExportInternal (const char* Name, unsigned Flags) -/* Mark the given symbol as an exported symbol */ -{ - SymEntry* S; - - /* Don't accept local symbols */ - if (IsLocalName (Name)) { - Error (ERR_ILLEGAL_LOCAL_USE); - return; - } - - /* Do we have such a symbol? */ - S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW); - if (S->Flags & SF_IMPORT) { - /* The symbol is already marked as imported external symbol */ - Error (ERR_SYM_ALREADY_IMPORT, Name); - return; - } - - /* If the symbol is marked as global, check the symbol size, then do - * silently remove the global flag - */ - if (S->Flags & SF_GLOBAL) { - if ((Flags & SF_ZP) != (S->Flags & SF_ZP)) { - Error (ERR_SYM_REDECL_MISMATCH, Name); - } - S->Flags &= ~SF_GLOBAL; - } - - /* Set the symbol data */ - S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags); -} - - - -void SymExport (const char* Name) -/* Mark the given symbol as an exported symbol */ -{ - SymExportInternal (Name, SF_NONE); -} - - - -void SymExportZP (const char* Name) -/* Mark the given symbol as an exported zeropage symbol */ -{ - SymExportInternal (Name, SF_ZP); -} - - - -static void SymGlobalInternal (const char* Name, unsigned Flags) -/* Mark the given symbol as a global symbol, that is, as a symbol that is - * either imported or exported. - */ -{ - SymEntry* S; - - /* Don't accept local symbols */ - if (IsLocalName (Name)) { - Error (ERR_ILLEGAL_LOCAL_USE); - return; - } - - /* Search for this symbol, create a new entry if needed */ - S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW); - - /* If the symbol is already marked as import or export, check the - * size of the definition, then bail out. */ - if (S->Flags & SF_IMPORT || S->Flags & SF_EXPORT) { - if ((Flags & SF_ZP) != (S->Flags & SF_ZP)) { - Error (ERR_SYM_REDECL_MISMATCH, Name); - } - return; - } - - /* Mark the symbol */ - S->Flags |= (SF_GLOBAL | Flags); -} - - - -void SymGlobal (const char* Name) -/* Mark the given symbol as a global symbol, that is, as a symbol that is - * either imported or exported. - */ -{ - SymGlobalInternal (Name, SF_NONE); -} - - - -void SymGlobalZP (const char* Name) -/* Mark the given symbol as a global zeropage symbol, that is, as a symbol - * that is either imported or exported. - */ -{ - SymGlobalInternal (Name, SF_ZP); -} - - - void SymConDes (const char* Name, unsigned Type, unsigned Prio) /* Mark the given symbol as a module constructor/destructor. This will also * mark the symbol as an export. Initializers may never be zero page symbols. @@ -560,7 +403,7 @@ void SymConDes (const char* Name, unsigned Type, unsigned Prio) } /* Check if the symbol was not already defined as ZP symbol */ - if ((S->Flags & SF_ZP) != 0) { + if (S->AddrSize == ADDR_SIZE_ZP) { Error (ERR_SYM_REDECL_MISMATCH, Name); } diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index ae343a9c0..8fda5f3a4 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -54,11 +54,6 @@ -/* Scope identifiers */ -#define SCOPE_ANY 0 -#define SCOPE_GLOBAL 1 -#define SCOPE_LOCAL 2 - /* A symbol table */ typedef struct SymTable SymTable; struct SymTable { @@ -66,6 +61,8 @@ struct SymTable { SymTable* Right; /* Pointer to greater entry */ SymTable* Parent; /* Link to enclosing scope if any */ SymTable* Childs; /* Pointer to child scopes */ + unsigned char AddrSize; /* Address size */ + unsigned char Type; /* Type of the scope */ unsigned Level; /* Lexical level */ unsigned TableSlots; /* Number of hash table slots */ unsigned TableEntries; /* Number of entries in the table */ @@ -85,13 +82,13 @@ SymTable* RootScope; /* Root symbol table */ -void SymEnterLevel (const char* ScopeName); +void SymEnterLevel (const char* ScopeName, unsigned AddrSize); /* Enter a new lexical level */ void SymLeaveLevel (void); /* Leave the current lexical level */ -SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags); +SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew); /* Find a scope in the given enclosing scope */ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew); @@ -100,31 +97,6 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew); * new entry created, or - in case AllocNew is zero - return 0. */ -void SymImport (const char* Name); -/* Mark the given symbol as an imported symbol */ - -void SymImportZP (const char* Name); -/* Mark the given symbol as a imported zeropage symbol */ - -void SymImportForced (const char* Name); -/* Mark the given symbol as a forced imported symbol */ - -void SymExport (const char* Name); -/* Mark the given symbol as an exported symbol */ - -void SymExportZP (const char* Name); -/* Mark the given symbol as an exported zeropage symbol */ - -void SymGlobal (const char* Name); -/* Mark the given symbol as a global symbol, that is, as a symbol that is - * either imported or exported. - */ - -void SymGlobalZP (const char* Name); -/* Mark the given symbol as a global zeropage symbol, that is, as a symbol - * that is either imported or exported. - */ - void SymConDes (const char* Name, unsigned Type, unsigned Prio); /* Mark the given symbol as a module constructor/destructor. This will also * mark the symbol as an export. Initializers may never be zero page symbols. diff --git a/src/common/addrsize.c b/src/common/addrsize.c new file mode 100644 index 000000000..845cb0e75 --- /dev/null +++ b/src/common/addrsize.c @@ -0,0 +1,60 @@ +/*****************************************************************************/ +/* */ +/* addrsize.c */ +/* */ +/* Address size definitions */ +/* */ +/* */ +/* */ +/* (C) 1998-2003 Ullrich von Bassewitz */ +/* Römerstraße 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +/* common */ +#include "addrsize.h" + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +const char* AddrSizeToStr (unsigned char AddrSize) +/* Return the name for an address size specifier */ +{ + switch (AddrSize) { + case ADDR_SIZE_DEFAULT: return "default"; + case ADDR_SIZE_ZP: return "zeropage"; + case ADDR_SIZE_ABS: return "absolute"; + case ADDR_SIZE_FAR: return "far"; + default: return "unknown"; + } +} + + + diff --git a/src/common/addrsize.h b/src/common/addrsize.h index d6297fe0a..86ed732e9 100644 --- a/src/common/addrsize.h +++ b/src/common/addrsize.h @@ -45,12 +45,23 @@ #define ADDR_SIZE_DEFAULT 0x00 -#define ADDR_SIZE_ZEROPAGE 0x01 -#define ADDR_SIZE_ABSOLUTE 0x02 +#define ADDR_SIZE_ZP 0x01 +#define ADDR_SIZE_ABS 0x02 #define ADDR_SIZE_FAR 0x03 +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +const char* AddrSizeToStr (unsigned char AddrSize); +/* Return the name for an address size specifier */ + + + /* End of addrsize.h */ #endif diff --git a/src/common/make/gcc.mak b/src/common/make/gcc.mak index 1f7590ec1..d178f44bb 100644 --- a/src/common/make/gcc.mak +++ b/src/common/make/gcc.mak @@ -10,6 +10,7 @@ LIB = common.a OBJS = abend.o \ + addrsize.o \ bitops.o \ chartype.o \ check.o \ diff --git a/src/common/make/watcom.mak b/src/common/make/watcom.mak index 346a693ce..72adf6887 100644 --- a/src/common/make/watcom.mak +++ b/src/common/make/watcom.mak @@ -10,7 +10,7 @@ export WATCOM = c:\\watcom export INCLUDE = $(WATCOM)\\h # We will use the windows compiler under linux (define as empty for windows) -WINE = wine -- +WINE = wine -- # Programs AR = $(WINE) WLIB @@ -55,6 +55,7 @@ endif # All library OBJ files OBJS = abend.obj \ + addrsize.obj \ bitops.obj \ chartype.obj \ check.obj \ diff --git a/src/common/segdefs.c b/src/common/segdefs.c index 0473ff224..b43272c1e 100644 --- a/src/common/segdefs.c +++ b/src/common/segdefs.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 2002-2003 Ullrich von Bassewitz */ +/* Römerstraße 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -45,17 +45,15 @@ -SegDef* NewSegDef (const char* Name, unsigned Type) +SegDef* NewSegDef (const char* Name, unsigned AddrSize) /* Create a new segment definition and return it */ { /* Allocate memory */ SegDef* D = xmalloc (sizeof (SegDef)); /* Initialize it */ - if (D) { - D->Name = xstrdup (Name); - D->Type = Type; - } + D->Name = xstrdup (Name); + D->AddrSize = AddrSize; /* Return the result */ return D; @@ -75,20 +73,7 @@ void FreeSegDef (SegDef* D) SegDef* DupSegDef (const SegDef* Def) /* Duplicate a segment definition and return it */ { - return NewSegDef (Def->Name, Def->Type); -} - - - -const char* SegTypeToStr (unsigned char Type) -/* Map a segment type into a string */ -{ - switch (Type) { - case SEGTYPE_ABS: return "abs"; - case SEGTYPE_ZP: return "zp"; - case SEGTYPE_FAR: return "far"; - default: return "unknown"; - } + return NewSegDef (Def->Name, Def->AddrSize); } diff --git a/src/common/segdefs.h b/src/common/segdefs.h index eb4fcfbb9..8c9adcbbb 100644 --- a/src/common/segdefs.h +++ b/src/common/segdefs.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -37,6 +37,11 @@ #define SEGDEFS_H + +/* common */ +#include "addrsize.h" + + /*****************************************************************************/ /* Data */ @@ -44,21 +49,15 @@ -/* Available segment types */ -#define SEGTYPE_DEFAULT 0 -#define SEGTYPE_ABS 1 -#define SEGTYPE_ZP 2 -#define SEGTYPE_FAR 3 - /* Segment definition */ typedef struct SegDef SegDef; struct SegDef { char* Name; /* Segment name */ - unsigned Type; /* Segment type, see above */ + unsigned AddrSize; /* Default address size */ }; /* Initializer for static SegDefs */ -#define STATIC_SEGDEF_INITIALIZER(name, type) { (name), (type) } +#define STATIC_SEGDEF_INITIALIZER(name, addrsize) { name, addrsize } @@ -68,7 +67,7 @@ struct SegDef { -SegDef* NewSegDef (const char* Name, unsigned Type); +SegDef* NewSegDef (const char* Name, unsigned AddrSize); /* Create a new segment definition and return it */ void FreeSegDef (SegDef* D); @@ -77,9 +76,6 @@ void FreeSegDef (SegDef* D); SegDef* DupSegDef (const SegDef* D); /* Duplicate a segment definition and return it */ -const char* SegTypeToStr (unsigned char Type); -/* Map a segment type into a string */ - /* End of segdefs.h */ diff --git a/src/ld65/condes.c b/src/ld65/condes.c index 2f9f29263..785ba82f9 100644 --- a/src/ld65/condes.c +++ b/src/ld65/condes.c @@ -36,6 +36,7 @@ #include /* common */ +#include "addrsize.h" #include "check.h" #include "coll.h" #include "fragdefs.h" @@ -127,7 +128,7 @@ static int ConDesCompare (void* Data, const void* E1, const void* E2) static void ConDesCreateOne (ConDesDesc* CD) /* Create one table if requested */ { - Segment* Seg; /* Segment for table */ + Segment* Seg; /* Segment for table */ Section* Sec; /* Section for table */ unsigned Count; /* Number of exports */ unsigned I; @@ -151,10 +152,10 @@ static void ConDesCreateOne (ConDesDesc* CD) CollSort (&CD->ExpList, ConDesCompare, CD); /* Get the segment for the table, create it if needed */ - Seg = GetSegment (CD->SegName, SEGTYPE_ABS, 0); + Seg = GetSegment (CD->SegName, ADDR_SIZE_ABS, 0); /* Create a new section for the table */ - Sec = NewSection (Seg, 1, SEGTYPE_ABS); + Sec = NewSection (Seg, 1, ADDR_SIZE_ABS); /* Walk over the exports and create a fragment for each one. We will use * the exported expression without copying it, since it's cheap and there diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 4a518702d..d42320dc8 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -70,7 +70,7 @@ static Segment* HashTab [HASHTAB_SIZE]; static unsigned SegCount = 0; /* Segment count */ -static Segment* SegRoot = 0; /* List of all segments */ +static Segment* SegRoot = 0; /* List of all segments */ @@ -80,7 +80,7 @@ static Segment* SegRoot = 0; /* List of all segments */ -static Segment* NewSegment (unsigned Name, unsigned char Type) +static Segment* NewSegment (unsigned Name, unsigned char AddrSize) /* Create a new segment and initialize it */ { unsigned Hash; @@ -98,7 +98,7 @@ static Segment* NewSegment (unsigned Name, unsigned char Type) S->AlignObj = 0; S->Align = 0; S->FillVal = 0; - S->Type = Type; + S->AddrSize = AddrSize; S->ReadOnly = 0; S->Relocatable = 0; S->Dumped = 0; @@ -119,7 +119,7 @@ static Segment* NewSegment (unsigned Name, unsigned char Type) -Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName) +Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName) /* Search for a segment and return an existing one. If the segment does not * exist, create a new one and return that. ObjName is only used for the error * message and may be NULL if the segment is linker generated. @@ -133,10 +133,10 @@ Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName) */ if (S == 0) { /* Create a new segment */ - S = NewSegment (Name, Type); + S = NewSegment (Name, AddrSize); } else { - /* Check if the existing segment has the requested type */ - if (S->Type != Type) { + /* Check if the existing segment has the requested address size */ + if (S->AddrSize != AddrSize) { /* Allow an empty object name */ if (ObjName == 0) { ObjName = "[linker generated]"; @@ -152,7 +152,7 @@ Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName) -Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) +Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize) /* Create a new section for the given segment */ { unsigned long V; @@ -168,7 +168,7 @@ Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) S->FragLast = 0; S->Size = 0; S->Align = Align; - S->Type = Type; + S->AddrSize = AddrSize; /* Calculate the alignment bytes needed for the section */ V = (0x01UL << S->Align) - 1; @@ -637,7 +637,7 @@ void PrintDbgSegments (FILE* F) /* Print the segment data */ fprintf (F, "segment\t\"%s\", 0x%06lX, 0x%04lX, %s, %s\n", GetString (S->Name), S->PC, S->Size, - SegTypeToStr (S->Type), + AddrSizeToStr (S->AddrSize), S->ReadOnly? "ro" : "rw"); } diff --git a/src/ld65/segments.h b/src/ld65/segments.h index 0df7e8fc3..aca4bf6ad 100644 --- a/src/ld65/segments.h +++ b/src/ld65/segments.h @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -64,7 +64,7 @@ struct Segment { struct ObjData* AlignObj; /* Module that requested the alignment */ unsigned char Align; /* Alignment needed */ unsigned char FillVal; /* Value to use for fill bytes */ - unsigned char Type; /* Type of segment */ + unsigned char AddrSize; /* Address size of segment */ unsigned char ReadOnly; /* True for readonly segments (config) */ unsigned char Relocatable; /* True if the segment is relocatable */ unsigned char Dumped; /* Did we dump this segment? */ @@ -83,7 +83,7 @@ struct Section { unsigned long Size; /* Size of the section */ unsigned char Align; /* Alignment */ unsigned char Fill; /* Fill bytes for alignment */ - unsigned char Type; /* Type of segment */ + unsigned char AddrSize; /* Address size of segment */ }; @@ -110,13 +110,13 @@ typedef unsigned (*SegWriteFunc) (ExprNode* E, /* The expression to write -Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName); +Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName); /* Search for a segment and return an existing one. If the segment does not * exist, create a new one and return that. ObjName is only used for the error * message and may be NULL if the segment is linker generated. */ -Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type); +Section* NewSection (Segment* Seg, unsigned char Align, unsigned char AddrSize); /* Create a new section for the given segment */ Section* ReadSection (FILE* F, struct ObjData* O); diff --git a/src/od65/dump.c b/src/od65/dump.c index d3f52a9e7..c01bbcbe7 100644 --- a/src/od65/dump.c +++ b/src/od65/dump.c @@ -37,6 +37,7 @@ #include /* common */ +#include "addrsize.h" #include "cddefs.h" #include "coll.h" #include "exprdefs.h" @@ -438,19 +439,9 @@ void DumpObjSegments (FILE* F, unsigned long Offset) unsigned Len = strlen (Name); unsigned long Size = Read32 (F); unsigned Align = (1U << Read8 (F)); - unsigned char Type = Read8 (F); + unsigned char AddrSize = Read8 (F); unsigned long FragCount = ReadVar (F); - /* Get the description for the type */ - const char* TypeDesc; - switch (Type) { - case SEGTYPE_DEFAULT: TypeDesc = "SEGTYPE_DEFAULT"; break; - case SEGTYPE_ABS: TypeDesc = "SEGTYPE_ABS"; break; - case SEGTYPE_ZP: TypeDesc = "SEGTYPE_ZP"; break; - case SEGTYPE_FAR: TypeDesc = "SEGTYPE_FAR"; break; - default: TypeDesc = "SEGTYPE_UNKNOWN"; break; - } - /* Print the header */ printf (" Index:%27u\n", I); @@ -458,7 +449,8 @@ void DumpObjSegments (FILE* F, unsigned long Offset) printf (" Name:%*s\"%s\"\n", 24-Len, "", Name); printf (" Size:%26lu\n", Size); printf (" Alignment:%21u\n", Align); - printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc); + printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize, + AddrSizeToStr (AddrSize)); printf (" Fragment count:%16lu\n", FragCount); /* Seek to the end of the segment data (start of next) */