Merge remote-tracking branch 'upstream/master' into pcenginetarget

This commit is contained in:
mrdudz
2015-07-11 13:05:26 +02:00
112 changed files with 3314 additions and 940 deletions

View File

@@ -62,6 +62,7 @@
#include "symtab.h"
#include "toklist.h"
#include "ulabel.h"
#include "macro.h"
@@ -417,6 +418,34 @@ static ExprNode* FuncDefined (void)
static ExprNode* FuncIsMnemonic (void)
/* Handle the .ISMNEMONIC, .ISMNEM builtin function */
{
int Instr = -1;
/* Check for a macro or an instruction depending on UbiquitousIdents */
if (CurTok.Tok == TOK_IDENT) {
if (UbiquitousIdents) {
/* Macros CAN be instructions, so check for them first */
if (FindMacro (&CurTok.SVal) == 0) {
Instr = FindInstruction (&CurTok.SVal);
}
} else {
/* Macros and symbols may NOT use the names of instructions, so just check for the instruction */
Instr = FindInstruction (&CurTok.SVal);
}
} else {
Error ("Identifier expected.");
}
/* Skip the name */
NextTok ();
return GenLiteralExpr (Instr > 0);
}
ExprNode* FuncHiByte (void)
/* Handle the .HIBYTE builtin function */
{
@@ -629,6 +658,85 @@ static ExprNode* FuncReferenced (void)
static ExprNode* FuncAddrSize (void)
/* Handle the .ADDRSIZE function */
{
StrBuf ScopeName = STATIC_STRBUF_INITIALIZER;
StrBuf Name = STATIC_STRBUF_INITIALIZER;
SymEntry* Sym;
int AddrSize;
int NoScope;
/* Assume we don't know the size */
AddrSize = 0;
/* Check for a cheap local which needs special handling */
if (CurTok.Tok == TOK_LOCAL_IDENT) {
/* Cheap local symbol */
Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING);
if (Sym == 0) {
Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal);
} else {
AddrSize = Sym->AddrSize;
}
/* Remember and skip SVal, terminate ScopeName so it is empty */
SB_Copy (&Name, &CurTok.SVal);
NextTok ();
SB_Terminate (&ScopeName);
} else {
/* Parse the scope and the name */
SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName);
/* Check if the parent scope is valid */
if (ParentScope == 0) {
/* No such scope */
SB_Done (&ScopeName);
SB_Done (&Name);
return GenLiteral0 ();
}
/* If ScopeName is empty, no explicit scope was specified. We have to
** search upper scope levels in this case.
*/
NoScope = SB_IsEmpty (&ScopeName);
/* If we did find a scope with the name, read the symbol defining the
** size, otherwise search for a symbol entry with the name and scope.
*/
if (NoScope) {
Sym = SymFindAny (ParentScope, &Name);
} else {
Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING);
}
/* If we found the symbol retrieve the size, otherwise complain */
if (Sym) {
AddrSize = Sym->AddrSize;
} else {
Error ("Unknown symbol or scope: `%m%p%m%p'", &ScopeName, &Name);
}
}
if (AddrSize == 0) {
Warning (1, "Unknown address size: `%m%p%m%p'", &ScopeName, &Name);
}
/* Free the string buffers */
SB_Done (&ScopeName);
SB_Done (&Name);
/* Return the size. */
return GenLiteralExpr (AddrSize);
}
static ExprNode* FuncSizeOf (void)
/* Handle the .SIZEOF function */
{
@@ -965,6 +1073,10 @@ static ExprNode* Factor (void)
N = Function (FuncBankByte);
break;
case TOK_ADDRSIZE:
N = Function (FuncAddrSize);
break;
case TOK_BLANK:
N = Function (FuncBlank);
break;
@@ -982,6 +1094,10 @@ static ExprNode* Factor (void)
N = Function (FuncDefined);
break;
case TOK_ISMNEMONIC:
N = Function (FuncIsMnemonic);
break;
case TOK_HIBYTE:
N = Function (FuncHiByte);
break;

View File

@@ -63,6 +63,7 @@ static const char* FeatureKeys[FEAT_COUNT] = {
"c_comments",
"force_range",
"underline_in_numbers",
"addrsize",
};
@@ -119,6 +120,7 @@ feature_t SetFeature (const StrBuf* Key)
case FEAT_C_COMMENTS: CComments = 1; break;
case FEAT_FORCE_RANGE: ForceRange = 1; break;
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break;
case FEAT_ADDRSIZE: AddrSize = 1; break;
default: /* Keep gcc silent */ break;
}

View File

@@ -65,6 +65,7 @@ typedef enum {
FEAT_C_COMMENTS,
FEAT_FORCE_RANGE,
FEAT_UNDERLINE_IN_NUMBERS,
FEAT_ADDRSIZE,
/* Special value: Number of features available */
FEAT_COUNT

View File

@@ -82,3 +82,4 @@ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */
unsigned char CComments = 0; /* Allow C like comments */
unsigned char ForceRange = 0; /* Force values into expected range */
unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */
unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */

View File

@@ -84,6 +84,8 @@ extern unsigned char OrgPerSeg; /* Make .org local to current seg */
extern unsigned char CComments; /* Allow C like comments */
extern unsigned char ForceRange; /* Force values into expected range */
extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */
extern unsigned char AddrSize; /* Allow .ADDRSIZE function */

View File

@@ -713,9 +713,9 @@ static const struct {
{ "ROR", 0x000006F, 0x62, 1, PutAll },
{ "RTI", 0x0000001, 0x40, 0, PutAll },
{ "RTS", 0x0000001, 0x60, 0, PutAll },
{ "SBC", 0x080A66C, 0xe0, 0, PutAll },
{ "SAX", 0x0000001, 0x22, 0, PutAll },
{ "SAY", 0x0000001, 0x42, 0, PutAll },
{ "SBC", 0x080A66C, 0xe0, 0, PutAll },
{ "SEC", 0x0000001, 0x38, 0, PutAll },
{ "SED", 0x0000001, 0xf8, 0, PutAll },
{ "SEI", 0x0000001, 0x78, 0, PutAll },

View File

@@ -303,6 +303,10 @@ static void SetSys (const char* Sys)
NewSymbol ("__SIM65C02__", 1);
break;
case TGT_OSIC1P:
NewSymbol ("__OSIC1P__", 1);
break;
case TGT_PCENGINE:
NewSymbol ("__PCE__", 1);
break;

View File

@@ -1964,6 +1964,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoA16 },
{ ccNone, DoA8 },
{ ccNone, DoAddr }, /* .ADDR */
{ ccNone, DoUnexpected }, /* .ADDRSIZE */
{ ccNone, DoAlign },
{ ccNone, DoASCIIZ },
{ ccNone, DoAssert },
@@ -2039,6 +2040,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoIncBin },
{ ccNone, DoInclude },
{ ccNone, DoInterruptor },
{ ccNone, DoUnexpected }, /* .ISMNEMONIC */
{ ccNone, DoInvalid }, /* .LEFT */
{ ccNone, DoLineCont },
{ ccNone, DoList },

View File

@@ -135,6 +135,7 @@ struct DotKeyword {
{ ".A16", TOK_A16 },
{ ".A8", TOK_A8 },
{ ".ADDR", TOK_ADDR },
{ ".ADDRSIZE", TOK_ADDRSIZE },
{ ".ALIGN", TOK_ALIGN },
{ ".AND", TOK_BOOLAND },
{ ".ASCIIZ", TOK_ASCIIZ },
@@ -222,6 +223,8 @@ struct DotKeyword {
{ ".INCBIN", TOK_INCBIN },
{ ".INCLUDE", TOK_INCLUDE },
{ ".INTERRUPTOR", TOK_INTERRUPTOR },
{ ".ISMNEM", TOK_ISMNEMONIC },
{ ".ISMNEMONIC", TOK_ISMNEMONIC },
{ ".LEFT", TOK_LEFT },
{ ".LINECONT", TOK_LINECONT },
{ ".LIST", TOK_LIST },
@@ -723,7 +726,24 @@ static token_t FindDotKeyword (void)
R = bsearch (&K, DotKeywords, sizeof (DotKeywords) / sizeof (DotKeywords [0]),
sizeof (DotKeywords [0]), CmpDotKeyword);
if (R != 0) {
/* By default, disable any somewhat experiemental DotKeyword. */
switch (R->Tok) {
case TOK_ADDRSIZE:
/* Disallow .ADDRSIZE function by default */
if (AddrSize == 0) {
return TOK_NONE;
}
break;
default:
break;
}
return R->Tok;
} else {
return TOK_NONE;
}

View File

@@ -696,10 +696,10 @@ void SymDump (FILE* F)
while (S) {
/* Ignore unused symbols */
if ((S->Flags & SF_UNUSED) != 0) {
if ((S->Flags & SF_UNUSED) == 0) {
fprintf (F,
"%m%-24p %s %s %s %s %s\n",
GetSymName (S),
"%-24s %s %s %s %s %s\n",
SB_GetConstBuf (GetSymName (S)),
(S->Flags & SF_DEFINED)? "DEF" : "---",
(S->Flags & SF_REFERENCED)? "REF" : "---",
(S->Flags & SF_IMPORT)? "IMP" : "---",

View File

@@ -123,6 +123,7 @@ typedef enum token_t {
TOK_A16 = TOK_FIRSTPSEUDO,
TOK_A8,
TOK_ADDR,
TOK_ADDRSIZE,
TOK_ALIGN,
TOK_ASCIIZ,
TOK_ASSERT,
@@ -198,6 +199,7 @@ typedef enum token_t {
TOK_INCBIN,
TOK_INCLUDE,
TOK_INTERRUPTOR,
TOK_ISMNEMONIC,
TOK_LEFT,
TOK_LINECONT,
TOK_LIST,

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2001-2012, Ullrich von Bassewitz */
/* (C) 2001-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -46,6 +46,7 @@
#include "codeseg.h"
#include "datatype.h"
#include "error.h"
#include "global.h"
#include "reginfo.h"
#include "symtab.h"
#include "codeinfo.h"
@@ -386,33 +387,35 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
** Search for it in the list of builtin functions.
*/
if (Name[0] == '_') {
/* Search in the symbol table, skip the leading underscore */
SymEntry* E = FindGlobalSym (Name+1);
/* Did we find it in the top level table? */
/* Did we find it in the top-level table? */
if (E && IsTypeFunc (E->Type)) {
FuncDesc* D = E->V.F.Func;
/* A function may use the A or A/X registers if it is a fastcall
** function. If it is not a fastcall function but a variadic one,
** it will use the Y register (the parameter size is passed here).
** In all other cases, no registers are used. However, we assume
** that any function will destroy all registers.
/* A variadic function will use the Y register (the parameter list
** size is passed there). A fastcall function will use the A or A/X
** registers. In all other cases, no registers are used. However,
** we assume that any function will destroy all registers.
*/
if (IsQualFastcall (E->Type) && D->ParamCount > 0) {
/* Will use registers depending on the last param */
unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
if (LastParamSize == 1) {
*Use = REG_A;
} else if (LastParamSize == 2) {
*Use = REG_AX;
} else {
*Use = REG_EAX;
}
} else if ((D->Flags & FD_VARIADIC) != 0) {
if ((D->Flags & FD_VARIADIC) != 0) {
*Use = REG_Y;
} else if (D->ParamCount > 0 &&
(AutoCDecl ?
IsQualFastcall (E->Type) :
!IsQualCDecl (E->Type))) {
/* Will use registers depending on the last param. */
switch (CheckedSizeOf (D->LastParam->Type)) {
case 1u:
*Use = REG_A;
break;
case 2u:
*Use = REG_AX;
break;
default:
*Use = REG_EAX;
}
} else {
/* Will not use any registers */
*Use = REG_NONE;

View File

@@ -766,12 +766,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
InsertEntry (D, X, D->IP++);
/* Lhs load entries can be removed */
if (LoadX->AM != AM65_IMM) {
D->Lhs.X.Flags |= LI_REMOVE;
}
if (LoadA->AM != AM65_IMM) {
D->Lhs.A.Flags |= LI_REMOVE;
}
D->Lhs.X.Flags |= LI_REMOVE;
D->Lhs.A.Flags |= LI_REMOVE;
} else if ((D->Rhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT &&
(D->Rhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) {
@@ -794,12 +790,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer
InsertEntry (D, X, D->IP++);
/* Rhs load entries can be removed */
if (LoadX->AM != AM65_IMM) {
D->Rhs.X.Flags |= LI_REMOVE;
}
if (LoadA->AM != AM65_IMM) {
D->Rhs.A.Flags |= LI_REMOVE;
}
D->Rhs.X.Flags |= LI_REMOVE;
D->Rhs.A.Flags |= LI_REMOVE;
} else if ((D->Rhs.A.Flags & LI_DIRECT) != 0 &&
(D->Rhs.X.Flags & LI_DIRECT) != 0) {

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -293,15 +293,15 @@ void PrintType (FILE* F, const Type* T)
/* Recursive call */
PrintType (F, T + 1);
if (T->A.L == UNSPECIFIED) {
fprintf (F, "[]");
fprintf (F, " []");
} else {
fprintf (F, "[%ld]", T->A.L);
fprintf (F, " [%ld]", T->A.L);
}
return;
case T_TYPE_PTR:
/* Recursive call */
PrintType (F, T + 1);
fprintf (F, "*");
fprintf (F, " *");
return;
case T_TYPE_FUNC:
fprintf (F, "function returning ");
@@ -659,7 +659,7 @@ Type* GetBaseElementType (Type* T)
** will return. Otherwise it will return the base element type, which means
** the element type that is not an array.
*/
{
{
while (IsTypeArray (T)) {
++T;
}

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -603,6 +603,16 @@ INLINE int IsQualCDecl (const Type* T)
# define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int IsQualCConv (const Type* T)
/* Return true if the given type has a calling convention qualifier */
{
return (T->C & T_QUAL_CCONV) != 0;
}
#else
# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0)
#endif
int IsVariadicFunc (const Type* T) attribute ((const));
/* Return true if this is a function type or pointer to function type with
** variable parameter list

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2013, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -85,7 +85,7 @@ struct StructInitData {
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
/* Parse a type specificier */
/* Parse a type specifier */
static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
/* Parse initialization of variables. Return the number of data bytes. */
@@ -335,18 +335,30 @@ static void FixQualifiers (Type* DataType)
T = DataType;
while (T->C != T_END) {
if (IsTypePtr (T)) {
/* Calling convention qualifier on the pointer? */
if (IsQualCConv (T)) {
/* Pull the convention off of the pointer */
Q = T[0].C & T_QUAL_CCONV;
T[0].C &= ~T_QUAL_CCONV;
/* Fastcall qualifier on the pointer? */
if (IsQualFastcall (T)) {
/* Pointer to function which is not fastcall? */
if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
/* Move the fastcall qualifier from the pointer to
** the function.
*/
T[0].C &= ~T_QUAL_FASTCALL;
T[1].C |= T_QUAL_FASTCALL;
/* Pointer to a function which doesn't have an explicit convention? */
if (IsTypeFunc (T + 1)) {
if (IsQualCConv (T + 1)) {
if ((T[1].C & T_QUAL_CCONV) == Q) {
Warning ("Pointer duplicates function's calling convention");
} else {
Error ("Function's and pointer's calling conventions are different");
}
} else {
if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) {
Error ("Variadic-function pointers cannot be __fastcall__");
} else {
/* Move the qualifier from the pointer to the function. */
T[1].C |= Q;
}
}
} else {
Error ("Invalid `_fastcall__' qualifier for pointer");
Error ("Not pointer to a function; can't use a calling convention");
}
}
@@ -355,8 +367,8 @@ static void FixQualifiers (Type* DataType)
if (Q == T_QUAL_NONE) {
/* No address size qualifiers specified */
if (IsTypeFunc (T+1)) {
/* Pointer to function. Use the qualifier from the function
** or the default if the function don't has one.
/* Pointer to function. Use the qualifier from the function,
** or the default if the function doesn't have one.
*/
Q = (T[1].C & T_QUAL_ADDRSIZE);
if (Q == T_QUAL_NONE) {
@@ -368,7 +380,7 @@ static void FixQualifiers (Type* DataType)
T[0].C |= Q;
} else {
/* We have address size qualifiers. If followed by a function,
** apply these also to the function.
** apply them to the function also.
*/
if (IsTypeFunc (T+1)) {
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
@@ -489,7 +501,7 @@ static void ParseEnumDecl (void)
static int ParseFieldWidth (Declaration* Decl)
/* Parse an optional field width. Returns -1 if no field width is speficied,
/* Parse an optional field width. Returns -1 if no field width is specified,
** otherwise the width of the field.
*/
{
@@ -862,7 +874,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
/* Parse a type specificier */
/* Parse a type specifier */
{
ident Ident;
SymEntry* Entry;
@@ -1376,13 +1388,13 @@ static FuncDesc* ParseFuncDecl (void)
static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Recursively process declarators. Build a type array in reverse order. */
{
/* Read optional function or pointer qualifiers. These modify the
** identifier or token to the right. For convenience, we allow the fastcall
** qualifier also for pointers here. If it is a pointer-to-function, the
** qualifier will later be transfered to the function itself. If it's a
/* Read optional function or pointer qualifiers. They modify the
** identifier or token to the right. For convenience, we allow a calling
** convention also for pointers here. If it's a pointer-to-function, the
** qualifier later will be transfered to the function itself. If it's a
** pointer to something else, it will be flagged as an error.
*/
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV);
/* Pointer to something */
if (CurTok.Tok == TOK_STAR) {
@@ -1390,10 +1402,10 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* Skip the star */
NextToken ();
/* Allow const, restrict and volatile qualifiers */
/* Allow const, restrict, and volatile qualifiers */
Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT);
/* Parse the type, the pointer points to */
/* Parse the type that the pointer points to */
Declarator (Spec, D, Mode);
/* Add the type */
@@ -1443,7 +1455,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
/* We cannot specify fastcall for variadic functions */
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
Error ("Variadic functions cannot be `__fastcall__'");
Error ("Variadic functions cannot be __fastcall__");
Qualifiers &= ~T_QUAL_FASTCALL;
}

View File

@@ -1,6 +1,7 @@
/* expr.c
**
** Ullrich von Bassewitz, 21.06.1998
** 1998-06-21, Ullrich von Bassewitz
** 2015-06-26, Greg King
*/
@@ -470,9 +471,11 @@ static void FunctionCall (ExprDesc* Expr)
/* Handle function pointers transparently */
IsFuncPtr = IsTypeFuncPtr (Expr->Type);
if (IsFuncPtr) {
/* Check wether it's a fastcall function that has parameters */
IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0);
/* Check whether it's a fastcall function that has parameters */
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && Func->ParamCount > 0 &&
(AutoCDecl ?
IsQualFastcall (Expr->Type + 1) :
!IsQualCDecl (Expr->Type + 1));
/* Things may be difficult, depending on where the function pointer
** resides. If the function pointer is an expression of some sort
@@ -517,7 +520,10 @@ static void FunctionCall (ExprDesc* Expr)
}
/* If we didn't inline the function, get fastcall info */
IsFastcall = IsQualFastcall (Expr->Type);
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 &&
(AutoCDecl ?
IsQualFastcall (Expr->Type) :
!IsQualCDecl (Expr->Type));
}
/* Parse the parameter list */
@@ -1707,8 +1713,13 @@ void hie10 (ExprDesc* Expr)
} else {
Error ("Illegal indirection");
}
/* The * operator yields an lvalue */
ED_MakeLVal (Expr);
/* If the expression points to an array, then don't convert the
** address -- it already is the location of the first element.
*/
if (!IsTypeArray (Expr->Type)) {
/* The * operator yields an lvalue */
ED_MakeLVal (Expr);
}
}
break;

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2012, Ullrich von Bassewitz */
/* (C) 2000-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -460,6 +460,9 @@ void NewFunc (SymEntry* Func)
*/
if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) {
g_importmainargs ();
/* The start-up code doesn't fast-call main(). */
Func->Type->C |= T_QUAL_CDECL;
}
/* Determine if this is a main function in a C99 environment that
@@ -478,13 +481,12 @@ void NewFunc (SymEntry* Func)
PushLiteralPool (Func);
/* If this is a fastcall function, push the last parameter onto the stack */
if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 &&
(AutoCDecl ?
IsQualFastcall (Func->Type) :
!IsQualCDecl (Func->Type))) {
unsigned Flags;
/* Fastcall functions may never have an ellipsis or the compiler is buggy */
CHECK ((D->Flags & FD_VARIADIC) == 0);
/* Generate the push */
if (IsTypeFunc (D->LastParam->Type)) {
/* Pointer to function */

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -44,6 +44,7 @@
unsigned char AddSource = 0; /* Add source lines as comments */
unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */
unsigned char DebugInfo = 0; /* Add debug info to the obj */
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
unsigned char DebugOptOutput = 0; /* Output debug stuff */

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2012, Ullrich von Bassewitz */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -52,6 +52,7 @@
/* Options */
extern unsigned char AddSource; /* Add source lines as comments */
extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */
extern unsigned char DebugInfo; /* Add debug info to the obj */
extern unsigned char PreprocessOnly; /* Just preprocess the input */
extern unsigned char DebugOptOutput; /* Output debug stuff */

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2013, Ullrich von Bassewitz */
/* (C) 2000-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -104,6 +104,7 @@ static void Usage (void)
"\n"
"Long options:\n"
" --add-source\t\t\tInclude source as comment\n"
" --all-cdecl\t\t\tMake functions default to __cdecl__\n"
" --bss-name seg\t\tSet the name of the BSS segment\n"
" --check-stack\t\t\tGenerate stack overflow checks\n"
" --code-name seg\t\tSet the name of the CODE segment\n"
@@ -258,6 +259,10 @@ static void SetSys (const char* Sys)
DefineNumericMacro ("__SIM65C02__", 1);
break;
case TGT_OSIC1P:
DefineNumericMacro ("__OSIC1P__", 1);
break;
case TGT_PCENGINE:
DefineNumericMacro ("__PCE__", 1);
break;
@@ -350,6 +355,15 @@ static void OptAddSource (const char* Opt attribute ((unused)),
static void OptAllCDecl (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Make functions default to cdecl instead of fastcall. */
{
AutoCDecl = 1;
}
static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --bss-name option */
{
@@ -790,6 +804,7 @@ int main (int argc, char* argv[])
/* Program long options */
static const LongOpt OptTab[] = {
{ "--add-source", 0, OptAddSource },
{ "--all-cdecl", 0, OptAllCDecl },
{ "--bss-name", 1, OptBssName },
{ "--check-stack", 0, OptCheckStack },
{ "--code-name", 1, OptCodeName },

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 1998-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -37,6 +37,7 @@
/* cc65 */
#include "funcdesc.h"
#include "global.h"
#include "symtab.h"
#include "typecmp.h"
@@ -245,23 +246,36 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
return;
}
}
if (LeftType == T_TYPE_FUNC) {
/* If a calling convention wasn't set explicitly,
** then assume the default one.
*/
if ((LeftQual & T_QUAL_CCONV) == T_QUAL_NONE) {
LeftQual |= (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
}
if ((RightQual & T_QUAL_CCONV) == T_QUAL_NONE) {
RightQual |= (AutoCDecl || IsVariadicFunc (rhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
}
}
if (LeftQual != RightQual) {
/* On the first indirection level, different qualifiers mean
** that the types are still compatible. On the second level,
** this is a (maybe minor) error, so we create a special
** return code, since a qualifier is dropped from a pointer.
** Starting from the next level, the types are incompatible
** if the qualifiers differ.
** that the types still are compatible. On the second level,
** that is a (maybe minor) error. We create a special return-code
** if a qualifier is dropped from a pointer. But, different calling
** conventions are incompatible. Starting from the next level,
** the types are incompatible if the qualifiers differ.
*/
/* (Debugging statement) */
/* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
switch (Indirections) {
case 0:
SetResult (Result, TC_STRICT_COMPATIBLE);
break;
case 1:
/* A non const value on the right is compatible to a
/* A non-const value on the right is compatible to a
** const one to the left, same for volatile.
*/
if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
@@ -270,7 +284,11 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
} else {
SetResult (Result, TC_STRICT_COMPATIBLE);
}
break;
if (LeftType != T_TYPE_FUNC || (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) {
break;
}
/* else fall through */
default:
SetResult (Result, TC_INCOMPATIBLE);
@@ -280,7 +298,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
/* Check for special type elements */
switch (LeftType) {
case T_TYPE_PTR:
++Indirections;
break;

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2011, Ullrich von Bassewitz */
/* (C) 2000-2015, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -50,7 +50,7 @@
/* Translation table with direct (no) translation */
static unsigned char CTNone[256] = {
static const unsigned char CTNone[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -69,8 +69,8 @@ static unsigned char CTNone[256] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
/* Translation table ISO-8859-1 -> ATASCII */
static const unsigned char CTAtari [256] = {
/* Translation table ISO-8859-1 -> AtASCII */
static const unsigned char CTAtari[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0xFD,0x08,0x7F,0x9B,0x0B,0x7D,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -89,8 +89,28 @@ static const unsigned char CTAtari [256] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
/* Translation table ISO-8859-1 -> PETSCII */
static const unsigned char CTPET [256] = {
/* Translation table ISO-8859-1 -> OSASCII */
static const unsigned char CTOSI[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7D,0x7C,0x7F,0x7E,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
/* Translation table ISO-8859-1 -> PetSCII */
static const unsigned char CTPET[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -142,6 +162,7 @@ static const TargetEntry TargetMap[] = {
{ "module", TGT_MODULE },
{ "nes", TGT_NES },
{ "none", TGT_NONE },
{ "osic1p", TGT_OSIC1P },
{ "pce", TGT_PCENGINE },
{ "pet", TGT_PET },
{ "plus4", TGT_PLUS4 },
@@ -168,6 +189,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
{ "plus4", CPU_6502, BINFMT_BINARY, CTPET },
{ "cbm510", CPU_6502, BINFMT_BINARY, CTPET },
{ "cbm610", CPU_6502, BINFMT_BINARY, CTPET },
{ "osic1p", CPU_6502, BINFMT_BINARY, CTOSI },
{ "pet", CPU_6502, BINFMT_BINARY, CTPET },
{ "bbc", CPU_6502, BINFMT_BINARY, CTNone },
{ "apple2", CPU_6502, BINFMT_BINARY, CTNone },

View File

@@ -64,6 +64,7 @@ typedef enum {
TGT_PLUS4,
TGT_CBM510,
TGT_CBM610,
TGT_OSIC1P,
TGT_PET,
TGT_BBC,
TGT_APPLE2,

View File

@@ -47,7 +47,7 @@
#define VER_MAJOR 2U
#define VER_MINOR 14U
#define VER_MINOR 15U

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2006 Ullrich von Bassewitz */
/* R<EFBFBD>merstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -66,6 +66,18 @@ void AddrCheck (unsigned Addr)
attr_t GetAttr (unsigned Addr)
/* Return the attribute for the given address */
{
/* Check the given address */
AddrCheck (Addr);
/* Return the attribute */
return AttrTab[Addr];
}
int SegmentDefined (unsigned Start, unsigned End)
/* Return true if the atSegment bit is set somewhere in the given range */
{
@@ -79,14 +91,18 @@ int SegmentDefined (unsigned Start, unsigned End)
int HaveSegmentChange (unsigned Addr)
/* Return true if the segment change attribute is set for the given address */
int IsSegmentEnd (unsigned Addr)
/* Return true if a segment ends at the given address */
{
/* Check the given address */
AddrCheck (Addr);
return (GetAttr (Addr) & atSegmentEnd) != 0x0000;
}
/* Return the attribute */
return (AttrTab[Addr] & atSegmentChange) != 0;
int IsSegmentStart (unsigned Addr)
/* Return true if a segment starts at the given address */
{
return (GetAttr (Addr) & atSegmentStart) != 0x0000;
}
@@ -145,18 +161,6 @@ void MarkAddr (unsigned Addr, attr_t Attr)
attr_t GetAttr (unsigned Addr)
/* Return the attribute for the given address */
{
/* Check the given address */
AddrCheck (Addr);
/* Return the attribute */
return AttrTab[Addr];
}
attr_t GetStyleAttr (unsigned Addr)
/* Return the style attribute for the given address */
{

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2006 Ullrich von Bassewitz */
/* R<EFBFBD>merstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -47,33 +47,34 @@
typedef enum attr_t {
/* Styles */
atDefault = 0x0000, /* Default style */
atCode = 0x0001,
atIllegal = 0x0002,
atByteTab = 0x0003, /* Same as illegal */
atDByteTab = 0x0004,
atWordTab = 0x0005,
atDWordTab = 0x0006,
atAddrTab = 0x0007,
atRtsTab = 0x0008,
atTextTab = 0x0009,
atSkip = 0x000A, /* Skip code completely */
atDefault = 0x0000, /* Default style */
atCode = 0x0001,
atIllegal = 0x0002,
atByteTab = 0x0003, /* Same as illegal */
atDByteTab = 0x0004,
atWordTab = 0x0005,
atDWordTab = 0x0006,
atAddrTab = 0x0007,
atRtsTab = 0x0008,
atTextTab = 0x0009,
atSkip = 0x000A, /* Skip code completely */
/* Label flags */
atNoLabel = 0x0000, /* No label for this address */
atExtLabel = 0x0010, /* External label */
atIntLabel = 0x0020, /* Internally generated label */
atDepLabel = 0x0040, /* Dependent label */
atUnnamedLabel = 0x0080, /* Unnamed label */
atNoLabel = 0x0000, /* No label for this address */
atExtLabel = 0x0010, /* External label */
atIntLabel = 0x0020, /* Internally generated label */
atDepLabel = 0x0040, /* Dependent label */
atUnnamedLabel = 0x0080, /* Unnamed label */
atLabelDefined = 0x0100, /* True if we defined the label */
atLabelDefined = 0x0100, /* True if we defined the label */
atStyleMask = 0x000F, /* Output style */
atLabelMask = 0x00F0, /* Label information */
atStyleMask = 0x000F, /* Output style */
atLabelMask = 0x00F0, /* Label information */
/* Segment */
atSegment = 0x0100, /* Code is in a segment */
atSegmentChange = 0x0200, /* Either segment start or segment end */
atSegment = 0x0100, /* Code is in a segment */
atSegmentEnd = 0x0200, /* Segment end */
atSegmentStart = 0x0400, /* Segment start */
} attr_t;
@@ -87,11 +88,17 @@ typedef enum attr_t {
void AddrCheck (unsigned Addr);
/* Check if the given address has a valid range */
attr_t GetAttr (unsigned Addr);
/* Return the attribute for the given address */
int SegmentDefined (unsigned Start, unsigned End);
/* Return true if the atSegment bit is set somewhere in the given range */
int HaveSegmentChange (unsigned Addr);
/* Return true if the segment change attribute is set for the given address */
int IsSegmentEnd (unsigned Addr);
/* Return true if a segment ends at the given address */
int IsSegmentStart (unsigned Addr);
/* Return true if a segment starts at the given address */
unsigned GetGranularity (attr_t Style);
/* Get the granularity for the given style */
@@ -102,9 +109,6 @@ void MarkRange (unsigned Start, unsigned End, attr_t Attr);
void MarkAddr (unsigned Addr, attr_t Attr);
/* Mark an address with an attribute */
attr_t GetAttr (unsigned Addr);
/* Return the attribute for the given address */
attr_t GetStyleAttr (unsigned Addr);
/* Return the style attribute for the given address */
@@ -114,5 +118,4 @@ attr_t GetLabelAttr (unsigned Addr);
/* End of attrtab.h */
#endif

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -65,12 +65,12 @@ static unsigned GetSpan (attr_t Style)
attr_t Attr;
if (MustDefLabel(PC+Count)) {
break;
}
}
Attr = GetAttr (PC+Count);
if ((Attr & atStyleMask) != Style) {
break;
}
if ((Attr & atSegmentChange)) {
if ((Attr & (atSegmentStart | atSegmentEnd))) {
break;
}
++Count;

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2011, Ullrich von Bassewitz */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -748,16 +748,13 @@ static void SegmentSection (void)
if (Start < 0) {
InfoError ("Start address is missing");
}
if (Start == End) {
InfoError ("Segment is empty");
}
if (Start > End) {
InfoError ("Start address of segment is greater than end address");
}
/* Check that segments do not overlap */
if (SegmentDefined ((unsigned) Start, (unsigned) End)) {
InfoError ("Segments cannot overlap");
InfoError ("Segments must not overlap");
}
/* Remember the segment data */

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 1998-2011, Ullrich von Bassewitz */
/* (C) 1998-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -60,6 +60,7 @@
#include "opctable.h"
#include "output.h"
#include "scanner.h"
#include "segment.h"
@@ -347,6 +348,8 @@ static void OptVersion (const char* Opt attribute ((unused)),
static void OneOpcode (unsigned RemainingBytes)
/* Disassemble one opcode */
{
unsigned I;
/* Get the opcode from the current address */
unsigned char OPC = GetCodeByte (PC);
@@ -356,6 +359,14 @@ static void OneOpcode (unsigned RemainingBytes)
/* Get the output style for the current PC */
attr_t Style = GetStyleAttr (PC);
/* If a segment begins here, then name that segment.
** Note that the segment is named even if its code is being skipped,
** because some of its later code might not be skipped.
*/
if (IsSegmentStart (PC)) {
StartSegment (GetSegmentStartName (PC), GetSegmentAddrSize (PC));
}
/* If we have a label at this address, output the label and an attached
** comment, provided that we aren't in a skip area.
*/
@@ -371,7 +382,8 @@ static void OneOpcode (unsigned RemainingBytes)
** - ...if we have enough bytes remaining for the code at this address.
** - ...if the current instruction is valid for the given CPU.
** - ...if there is no label somewhere between the instruction bytes.
** If any of these conditions is false, switch to data mode.
** - ...if there is no segment change between the instruction bytes.
** If any one of those conditions is false, switch to data mode.
*/
if (Style == atDefault) {
if (D->Size > RemainingBytes) {
@@ -381,9 +393,15 @@ static void OneOpcode (unsigned RemainingBytes)
Style = atIllegal;
MarkAddr (PC, Style);
} else {
unsigned I;
for (I = 1; I < D->Size; ++I) {
if (HaveLabel (PC+I) || HaveSegmentChange (PC+I)) {
for (I = PC + D->Size; --I > PC; ) {
if (HaveLabel (I) || IsSegmentStart (I)) {
Style = atIllegal;
MarkAddr (PC, Style);
break;
}
}
for (I = 0; I < D->Size - 1u; ++I) {
if (IsSegmentEnd (PC + I)) {
Style = atIllegal;
MarkAddr (PC, Style);
break;
@@ -406,7 +424,6 @@ static void OneOpcode (unsigned RemainingBytes)
*/
if (D->Size <= RemainingBytes) {
/* Output labels within the next insn */
unsigned I;
for (I = 1; I < D->Size; ++I) {
ForwardLabel (I);
}
@@ -453,7 +470,16 @@ static void OneOpcode (unsigned RemainingBytes)
DataByteLine (1);
++PC;
break;
}
/* Change back to the default CODE segment if
** a named segment stops at the current address.
*/
for (I = D->Size; I >= 1; --I) {
if (IsSegmentEnd (PC - I)) {
EndSegment ();
break;
}
}
}

View File

@@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2000-2009, Ullrich von Bassewitz */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -63,6 +63,8 @@ static unsigned Col = 1; /* Current column */
static unsigned Line = 0; /* Current line on page */
static unsigned Page = 1; /* Current output page */
static const char* SegmentName = 0; /* Name of current segment */
/*****************************************************************************/
@@ -223,23 +225,6 @@ void DefConst (const char* Name, const char* Comment, unsigned Addr)
void StartSegment (const char* Name, unsigned AddrSize)
/* Start a segment */
{
if (Pass == PassCount) {
Output (".segment");
Indent (ACol);
if (AddrSize == ADDR_SIZE_DEFAULT) {
Output ("\"%s\"", Name);
} else {
Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize));
}
LineFeed ();
}
}
void DataByteLine (unsigned ByteCount)
/* Output a line with bytes */
{
@@ -335,6 +320,39 @@ void SeparatorLine (void)
void StartSegment (const char* Name, unsigned AddrSize)
/* Start a segment */
{
if (Pass == PassCount) {
LineFeed ();
Output (".segment");
Indent (ACol);
SegmentName = Name;
Output ("\"%s\"", Name);
if (AddrSize != ADDR_SIZE_DEFAULT) {
Output (": %s", AddrSizeToStr (AddrSize));
}
LineFeed ();
LineFeed ();
}
}
void EndSegment (void)
/* End a segment */
{
LineFeed ();
Output ("; End of \"%s\" segment", SegmentName);
LineFeed ();
SeparatorLine ();
Output (".code");
LineFeed ();
LineFeed ();
}
void UserComment (const char* Comment)
/* Output a comment line */
{

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2000-2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2000-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -74,12 +74,6 @@ void DefForward (const char* Name, const char* Comment, unsigned Offs);
void DefConst (const char* Name, const char* Comment, unsigned Addr);
/* Define an address constant */
void StartSegment (const char* Name, unsigned AddrSize);
/* Start a segment */
void EndSegment (void);
/* End a segment */
void OneDataByte (void);
/* Output a .byte line with the current code byte */
@@ -99,6 +93,12 @@ void DataDWordLine (unsigned ByteCount);
void SeparatorLine (void);
/* Print a separator line */
void StartSegment (const char* Name, unsigned AddrSize);
/* Start a segment */
void EndSegment (void);
/* End a segment */
void UserComment (const char* Comment);
/* Output a comment line */
@@ -111,5 +111,4 @@ void OutputSettings (void);
/* End of output.h */
#endif

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2007-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -58,18 +58,15 @@
typedef struct Segment Segment;
struct Segment {
Segment* NextStart; /* Pointer to next segment */
Segment* NextEnd; /* Pointer to next segment */
unsigned long Start;
unsigned long End;
unsigned AddrSize;
char Name[1]; /* Name, dynamically allocated */
};
/* Tables containing the segments. A segment is inserted using it's hash
** value. Collision is done by single linked lists.
/* Table containing the segments. A segment is inserted using its hash
** value. Collisions are handled by single-linked lists.
*/
static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */
static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */
@@ -90,20 +87,53 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name)
/* Fill in the data */
S->Start = Start;
S->End = End;
S->AddrSize = ADDR_SIZE_ABS;
memcpy (S->Name, Name, Len + 1);
/* Insert the segment into the hash tables */
/* Insert the segment into the hash table */
S->NextStart = StartTab[Start % HASH_SIZE];
StartTab[Start % HASH_SIZE] = S;
S->NextEnd = EndTab[End % HASH_SIZE];
EndTab[End % HASH_SIZE] = S;
/* Mark start and end of the segment */
MarkAddr (Start, atSegmentChange);
MarkAddr (End, atSegmentChange);
MarkAddr (Start, atSegmentStart);
MarkAddr (End, atSegmentEnd);
/* Mark the addresses within the segment */
MarkRange (Start, End, atSegment);
}
char* GetSegmentStartName (unsigned Addr)
/* Return the name of the segment which starts at the given address */
{
Segment* S = StartTab[Addr % HASH_SIZE];
/* Search the collision list for the exact address */
while (S != 0) {
if (S->Start == Addr) {
return S->Name;
}
S = S->NextStart;
}
return 0;
}
unsigned GetSegmentAddrSize (unsigned Addr)
/* Return the address size of the segment which starts at the given address */
{
Segment* S = StartTab[Addr % HASH_SIZE];
/* Search the collision list for the exact address */
while (S != 0) {
if (S->Start == Addr) {
return S->AddrSize;
}
S = S->NextStart;
}
return 0;
}

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 2007 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 2007-2014, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -47,8 +47,13 @@
void AddAbsSegment (unsigned Start, unsigned End, const char* Name);
/* Add an absolute segment to the segment table */
char* GetSegmentStartName (unsigned Addr);
/* Return the name of the segment which starts at the given address */
unsigned GetSegmentAddrSize (unsigned Addr);
/* Return the address size of the segment which starts at the given address */
/* End of segment.h */
#endif