From 1fbf554c6370e8d4c50393e3b78cdae9c32129f9 Mon Sep 17 00:00:00 2001 From: cuz Date: Fri, 4 May 2001 16:41:23 +0000 Subject: [PATCH] Working on the new backend git-svn-id: svn://svn.cc65.org/cc65/trunk@710 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 75 ++++++++++++------ src/cc65/codeent.h | 15 ++-- src/cc65/codelab.c | 17 ++++- src/cc65/codelab.h | 3 + src/cc65/codeopt.c | 186 ++++++++++++++++++++++++++++++++++++++------- src/cc65/codeseg.c | 174 ++++++++++++++++++++++++++++-------------- src/cc65/codeseg.h | 9 +++ src/cc65/global.c | 5 +- src/cc65/global.h | 9 ++- src/cc65/main.c | 2 - src/cc65/opcodes.c | 18 +++++ src/cc65/opcodes.h | 5 ++ 12 files changed, 396 insertions(+), 122 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index 9cf4d0688..2f980671a 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -39,6 +39,7 @@ /* cc65 */ #include "error.h" +#include "global.h" /* b6502 */ #include "codeinfo.h" @@ -71,9 +72,10 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo) E->AM = AM; E->Size = GetInsnSize (E->OPC, E->AM); E->Hints = 0; - E->Arg.Num = 0; + E->Arg = 0; + E->Num = 0; E->Flags = 0; - E->Usage = D->Info & (CI_MASK_USE | CI_MASK_CHG); + E->Info = D->Info | GetAMUseInfo (AM); E->JumpTo = JumpTo; InitCollection (&E->Labels); @@ -91,7 +93,8 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo) void FreeCodeEntry (CodeEntry* E) /* Free the given code entry */ { - /* ## Free the string argument if we have one */ + /* Free the string argument if we have one */ + xfree (E->Arg); /* Cleanup the collection */ DoneCollection (&E->Labels); @@ -102,77 +105,86 @@ void FreeCodeEntry (CodeEntry* E) +int CodeEntryHasLabel (const CodeEntry* E) +/* Check if the given code entry has labels attached */ +{ + return (CollCount (&E->Labels) > 0); +} + + + void OutputCodeEntry (FILE* F, const CodeEntry* E) /* Output the code entry to a file */ { const OPCDesc* D; + unsigned Chars; /* If we have a label, print that */ unsigned LabelCount = CollCount (&E->Labels); unsigned I; for (I = 0; I < LabelCount; ++I) { - OutputCodeLabel (F, CollConstAt (&E->Labels, I)); + OutputCodeLabel (F, CollConstAt (&E->Labels, I)); } /* Get the opcode description */ D = GetOPCDesc (E->OPC); /* Print the mnemonic */ - fprintf (F, "\t%s", D->Mnemo); + Chars = fprintf (F, "\t%s", D->Mnemo); /* Print the operand */ switch (E->AM) { - case AM_IMP: - /* implicit */ - break; + case AM_IMP: + /* implicit */ + break; - case AM_ACC: - /* accumulator */ - fprintf (F, "\ta"); - break; + case AM_ACC: + /* accumulator */ + Chars += fprintf (F, "%*sa", 9-Chars, ""); + break; - case AM_IMM: - /* immidiate */ - fprintf (F, "\t#%s", E->Arg.Expr); - break; + case AM_IMM: + /* immidiate */ + Chars += fprintf (F, "%*s#%s", 9-Chars, "", E->Arg); + break; - case AM_ZP: - case AM_ABS: + case AM_ZP: + case AM_ABS: /* zeropage and absolute */ - fprintf (F, "\t%s", E->Arg.Expr); + Chars += fprintf (F, "%*s%s", 9-Chars, "", E->Arg); break; case AM_ZPX: case AM_ABSX: /* zeropage,X and absolute,X */ - fprintf (F, "\t%s,x", E->Arg.Expr); + Chars += fprintf (F, "%*s%s,x", 9-Chars, "", E->Arg); break; case AM_ABSY: /* absolute,Y */ - fprintf (F, "\t%s,y", E->Arg.Expr); + Chars += fprintf (F, "%*s%s,y", 9-Chars, "", E->Arg); break; case AM_ZPX_IND: /* (zeropage,x) */ - fprintf (F, "\t(%s,x)", E->Arg.Expr); + Chars += fprintf (F, "%*s(%s,x)", 9-Chars, "", E->Arg); break; case AM_ZP_INDY: /* (zeropage),y */ - fprintf (F, "\t(%s),y", E->Arg.Expr); + Chars += fprintf (F, "%*s(%s),y", 9-Chars, "", E->Arg); break; case AM_ZP_IND: /* (zeropage) */ - fprintf (F, "\t(%s)", E->Arg.Expr); + Chars += fprintf (F, "%*s(%s)", 9-Chars, "", E->Arg); break; case AM_BRA: /* branch */ CHECK (E->JumpTo != 0); - fprintf (F, "\t%s", E->JumpTo->Name); + Chars += fprintf (F, "%*s%s", 9-Chars, "", E->JumpTo->Name); break; default: @@ -180,6 +192,19 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E) } + /* Print usage info if requested by the debugging flag */ +// if (Debug) { + Chars += fprintf (F, + "%*s; USE: %c%c%c CHG: %c%c%c", + 30-Chars, "", + (E->Info & CI_USE_A)? 'A' : '_', + (E->Info & CI_USE_X)? 'X' : '_', + (E->Info & CI_USE_Y)? 'Y' : '_', + (E->Info & CI_CHG_A)? 'A' : '_', + (E->Info & CI_CHG_X)? 'X' : '_', + (E->Info & CI_CHG_Y)? 'Y' : '_'); +// } + /* Terminate the line */ fprintf (F, "\n"); } diff --git a/src/cc65/codeent.h b/src/cc65/codeent.h index 15acff365..77a1a7a12 100644 --- a/src/cc65/codeent.h +++ b/src/cc65/codeent.h @@ -55,6 +55,10 @@ +/* Flags used */ +#define CEF_USERMARK 0x0001U /* Generic mark by user functions */ +#define CEF_NUMARG 0x0002U /* Insn has numerical argument */ + /* Code entry structure */ typedef struct CodeEntry CodeEntry; struct CodeEntry { @@ -62,12 +66,10 @@ struct CodeEntry { am_t AM; /* Adressing mode */ unsigned char Size; /* Estimated size */ unsigned char Hints; /* Hints for this entry */ - union { - unsigned Num; /* Numeric argument */ - char* Expr; /* Textual argument */ - } Arg; + char* Arg; /* Argument as string */ + unsigned Num; /* Numeric argument */ unsigned short Flags; /* Flags */ - unsigned short Usage; /* Register usage for this entry */ + unsigned short Info; /* Register usage info for this entry */ CodeLabel* JumpTo; /* Jump label */ Collection Labels; /* Labels for this instruction */ }; @@ -86,6 +88,9 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo); void FreeCodeEntry (CodeEntry* E); /* Free the given code entry */ +int CodeEntryHasLabel (const CodeEntry* E); +/* Check if the given code entry has labels attached */ + void OutputCodeEntry (FILE* F, const CodeEntry* E); /* Output the code entry to a file */ diff --git a/src/cc65/codelab.c b/src/cc65/codelab.c index bc52e5878..e02fd7946 100644 --- a/src/cc65/codelab.c +++ b/src/cc65/codelab.c @@ -36,7 +36,8 @@ /* common */ #include "xmalloc.h" -/* cc65 */ +/* b6502 */ +#include "codeent.h" #include "label.h" @@ -82,6 +83,18 @@ void FreeCodeLabel (CodeLabel* L) +void AddLabelRef (CodeLabel* L, struct CodeEntry* E) +/* Let the CodeEntry E reference the label L */ +{ + /* The insn at E jumps to this label */ + E->JumpTo = L; + + /* Remember that in the label */ + CollAppend (&L->JumpFrom, E); +} + + + unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E) /* Remove a reference to this label, return the number of remaining references */ { @@ -97,7 +110,7 @@ unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E) void OutputCodeLabel (FILE* F, const CodeLabel* L) /* Output the code label to a file */ { - fprintf (F, "%s:\n", L->Name); + fprintf (F, "%s:", L->Name); } diff --git a/src/cc65/codelab.h b/src/cc65/codelab.h index 2193ada38..8e6ef97bb 100644 --- a/src/cc65/codelab.h +++ b/src/cc65/codelab.h @@ -89,6 +89,9 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash); void FreeCodeLabel (CodeLabel* L); /* Free the given code label */ +void AddLabelRef (CodeLabel* L, struct CodeEntry* E); +/* Let the CodeEntry E reference the label L */ + unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E); /* Remove a reference to this label, return the number of remaining references */ diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index c4e6040a3..384a41455 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -33,14 +33,21 @@ +/* common */ +#include "print.h" + +/* cc65 */ +#include "global.h" + /* b6502 */ #include "codeent.h" +#include "codeinfo.h" #include "codeopt.h" /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ @@ -53,7 +60,7 @@ static unsigned OptChanges; /*****************************************************************************/ -/* Remove dead jumps */ +/* Remove dead jumps */ /*****************************************************************************/ @@ -80,34 +87,15 @@ static void OptDeadJumps (CodeSeg* S) /* Check if it's a branch, if it has a local target, and if the target * is the next instruction. */ - if (E->AM == AM_BRA) { - printf ("BRA on entry %u:\n", I); - if (E->JumpTo) { - printf (" JumpTo ok\n"); - if (E->JumpTo->Owner == CollAt (&S->Entries, I+1)) { - printf (" Branch to next insn\n"); - } - } - } - if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) { - /* Remember the label */ - CodeLabel* L = E->JumpTo; + /* Delete the dead jump */ + DelCodeSegLine (S, I); - /* Jump to next instruction, remove it */ - unsigned Remaining = RemoveLabelRef (L, E); - CollDelete (&S->Entries, I); - FreeCodeEntry (E); + /* Keep the number of entries updated */ --Count; - /* If the label has no more references, remove it */ - if (Remaining == 0) { - CollDeleteItem (&L->Owner->Labels, L); - FreeCodeLabel (L); - } - - /* Remember we had changes */ + /* Remember, we had changes */ ++OptChanges; } else { @@ -121,6 +109,131 @@ static void OptDeadJumps (CodeSeg* S) +/*****************************************************************************/ +/* Remove dead code */ +/*****************************************************************************/ + + + +static void OptDeadCode (CodeSeg* S) +/* Remove dead code (code that follows an unconditional jump or an rts/rti + * and has no label) + */ +{ + unsigned I; + + /* Get the number of entries, bail out if we have less than two entries */ + unsigned Count = CollCount (&S->Entries); + if (Count < 2) { + return; + } + + /* Walk over all entries minus the last one */ + I = 0; + while (I < Count-1) { + + /* Get this entry */ + CodeEntry* E = CollAt (&S->Entries, I); + + /* Check if it's an unconditional branch, and if the next entry has + * no labels attached + */ + if ((E->OPC == OPC_JMP || E->OPC == OPC_BRA || E->OPC == OPC_RTS || E->OPC == OPC_RTI) && + !CodeEntryHasLabel (CollAt (&S->Entries, I+1))) { + + /* Delete the next entry */ + DelCodeSegLine (S, I+1); + + /* Keep the number of entries updated */ + --Count; + + /* Remember, we had changes */ + ++OptChanges; + + } else { + + /* Next entry */ + ++I; + + } + } +} + + + +/*****************************************************************************/ +/* Optimize jump cascades */ +/*****************************************************************************/ + + + +static void OptJumpCascades (CodeSeg* S) +/* Optimize jump cascades (jumps to jumps). In such a case, the jump is + * replaced by a jump to the final location. This will in some cases produce + * worse code, because some jump targets are no longer reachable by short + * branches, but this is quite rare, so there are more advantages than + * disadvantages. + */ +{ + unsigned I; + + /* Get the number of entries, bail out if we have no entries */ + unsigned Count = CollCount (&S->Entries); + if (Count == 0) { + return; + } + + /* Walk over all entries */ + I = 0; + while (I < Count) { + + CodeLabel* OldLabel; + CodeLabel* NewLabel; + + /* Get this entry */ + CodeEntry* E = CollAt (&S->Entries, I); + + /* Check if it's a branch, if it has a label attached, and if the + * instruction at this label is also a branch. + */ + if (E->AM == AM_BRA && + (OldLabel = E->JumpTo) != 0 && + OldLabel->Owner->AM == AM_BRA && + (NewLabel = OldLabel->Owner->JumpTo) != 0) { + + /* Get the instruction that has the new label attached */ + CodeEntry* N = OldLabel->Owner; + + /* Remove the reference to our label and delete it if this was + * the last reference. + */ + if (RemoveLabelRef (OldLabel, E) == 0) { + /* Delete it */ + DelCodeLabel (S, OldLabel); + } + + /* Remove usage information from the entry and use the usage + * information from the new instruction instead. + */ + E->Info &= ~(CI_MASK_USE | CI_MASK_CHG); + E->Info |= N->Info & ~(CI_MASK_USE | CI_MASK_CHG); + + /* Use the new label */ + AddLabelRef (NewLabel, E); + + /* Remember ,we had changes */ + ++OptChanges; + + } + + /* Next entry */ + ++I; + + } +} + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -130,15 +243,34 @@ static void OptDeadJumps (CodeSeg* S) void RunOpt (CodeSeg* S) /* Run the optimizer */ { - printf ("Optimize\n"); + typedef void (*OptFunc) (CodeSeg*); + + /* Table with optimizer steps - are called in this order */ + static const OptFunc OptFuncs [] = { + OptJumpCascades, /* Optimize jump cascades */ + OptDeadJumps, /* Remove dead jumps */ + OptDeadCode, /* Remove dead code */ + }; /* Repeat all steps until there are no more changes */ do { + unsigned long Flags; + unsigned I; + /* Reset the number of changes */ OptChanges = 0; - OptDeadJumps (S); + /* Run all optimization steps */ + Flags = 1UL; + for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) { + if ((OptDisable & Flags) == 0) { + OptFuncs[I] (S); + } else if (Verbosity > 0 || Debug) { + printf ("Optimizer pass %u skipped\n", I); + } + Flags <<= 1; + } } while (OptChanges > 0); } diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index b318b7739..b67585d4e 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -136,10 +136,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) * white space, for example. */ { - char Mnemo[16]; + char Mnemo[16]; const OPCDesc* OPC; am_t AM = 0; /* Initialize to keep gcc silent */ - char Expr[64]; + char Arg[64]; char Reg; CodeEntry* E; CodeLabel* Label; @@ -160,7 +160,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) L = SkipSpace (L); /* Get the addressing mode */ - Expr[0] = '\0'; + Arg[0] = '\0'; switch (*L) { case '\0': @@ -170,13 +170,13 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) case '#': /* Immidiate */ - StrCopy (Expr, sizeof (Expr), L+1); + StrCopy (Arg, sizeof (Arg), L+1); AM = AM_IMM; break; case '(': /* Indirect */ - L = ReadToken (L+1, ",)", Expr, sizeof (Expr)); + L = ReadToken (L+1, ",)", Arg, sizeof (Arg)); /* Check for errors */ if (*L == '\0') { @@ -214,7 +214,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) } L = SkipSpace (L+1); if (*L != '\0') { - Error ("ASM code error: syntax error"); + Error ("ASM code error: syntax error"); return 0; } AM = AM_ZP_INDY; @@ -238,7 +238,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) default: /* Absolute, maybe indexed */ - L = ReadToken (L, ",", Expr, sizeof (Expr)); + L = ReadToken (L, ",", Arg, sizeof (Arg)); if (*L == '\0') { /* Assume absolute */ AM = AM_ABS; @@ -257,7 +257,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) AM = AM_ABSY; } else { Error ("ASM code error: syntax error"); - return 0; + return 0; } if (*L != '\0') { Error ("ASM code error: syntax error"); @@ -273,7 +273,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) * if it does not exist. Ignore anything but local labels here. */ Label = 0; - if ((OPC->Info & CI_MASK_BRA) == CI_BRA && Expr[0] == 'L') { + if ((OPC->Info & CI_MASK_BRA) == CI_BRA && Arg[0] == 'L') { unsigned Hash; @@ -284,13 +284,13 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) AM = AM_BRA; /* Generate the hash over the label, then search for the label */ - Hash = HashStr (Expr) % CS_LABEL_HASH_SIZE; - Label = FindCodeLabel (S, Expr, Hash); + Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE; + Label = FindCodeLabel (S, Arg, Hash); /* If we don't have the label, it's a forward ref - create it */ if (Label == 0) { /* Generate a new label */ - Label = NewCodeSegLabel (S, Expr, Hash); + Label = NewCodeSegLabel (S, Arg, Hash); } } @@ -298,9 +298,9 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) * structure and initialize it. */ E = NewCodeEntry (OPC, AM, Label); - if (Expr[0] != '\0') { + if (Arg[0] != '\0') { /* We have an additional expression */ - E->Arg.Expr = xstrdup (Expr); + E->Arg = xstrdup (Arg); } /* Return the new code entry */ @@ -342,34 +342,7 @@ CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName) void FreeCodeSeg (CodeSeg* S) /* Free a code segment including all code entries */ { - unsigned I, Count; - - /* Free the names */ - xfree (S->SegName); - xfree (S->FuncName); - - /* Free the entries */ - Count = CollCount (&S->Entries); - for (I = 0; I < Count; ++I) { - FreeCodeEntry (CollAt (&S->Entries, I)); - } - - /* Free the collections */ - DoneCollection (&S->Entries); - DoneCollection (&S->Labels); - - /* Free all labels */ - for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) { - CodeLabel* L = S->LabelHash[I]; - while (L) { - CodeLabel* Tmp = L; - L = L->Next; - FreeCodeLabel (Tmp); - } - } - - /* Free the struct */ - xfree (S); + FAIL ("Not implemented"); } @@ -422,7 +395,7 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...) E = 0; /* Assume no insn created */ switch (*L) { - case '\0': + case '\0': /* Empty line, just ignore it */ break; @@ -469,6 +442,45 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...) +void DelCodeSegLine (CodeSeg* S, unsigned Index) +/* Delete an entry from the code segment. This includes deleting any associated + * labels, removing references to labels and even removing the referenced labels + * if the reference count drops to zero. + */ +{ + /* Get the code entry for the given index */ + CodeEntry* E = CollAt (&S->Entries, Index); + + /* Remove any labels associated with this entry */ + unsigned Count; + while ((Count = CollCount (&E->Labels)) > 0) { + DelCodeLabel (S, CollAt (&E->Labels, Count-1)); + } + + /* If this insn references a label, remove the reference. And, if the + * the reference count for this label drops to zero, remove this label. + */ + if (E->JumpTo) { + + /* Remove the reference */ + if (RemoveLabelRef (E->JumpTo, E) == 0) { + /* No references remaining, remove the label */ + DelCodeLabel (S, E->JumpTo); + } + + /* Reset the label pointer to avoid problems later */ + E->JumpTo = 0; + } + + /* Delete the pointer to the insn */ + CollDelete (&S->Entries, Index); + + /* Delete the instruction itself */ + FreeCodeEntry (E); +} + + + void AddCodeLabel (CodeSeg* S, const char* Name) /* Add a code label for the next instruction to follow */ { @@ -480,11 +492,11 @@ void AddCodeLabel (CodeSeg* S, const char* Name) /* Did we find it? */ if (L) { - /* We found it - be sure it does not already have an owner */ - CHECK (L->Owner == 0); + /* We found it - be sure it does not already have an owner */ + CHECK (L->Owner == 0); } else { - /* Not found - create a new one */ - L = NewCodeSegLabel (S, Name, Hash); + /* Not found - create a new one */ + L = NewCodeSegLabel (S, Name, Hash); } /* We do now have a valid label. Remember it for later */ @@ -493,6 +505,49 @@ void AddCodeLabel (CodeSeg* S, const char* Name) +void DelCodeLabel (CodeSeg* S, CodeLabel* L) +/* Remove references from this label and delete it. */ +{ + unsigned Count, I; + + /* Get the first entry in the hash chain */ + CodeLabel* List = S->LabelHash[L->Hash]; + + /* First, remove the label from the hash chain */ + if (List == L) { + /* First entry in hash chain */ + S->LabelHash[L->Hash] = L->Next; + } else { + /* Must search through the chain */ + while (List->Next != L) { + /* If we've reached the end of the chain, something is *really* wrong */ + CHECK (List->Next != 0); + /* Next entry */ + List = List->Next; + } + /* The next entry is the one, we have been searching for */ + List->Next = L->Next; + } + + /* Remove references from insns jumping to this label */ + Count = CollCount (&L->JumpFrom); + for (I = 0; I < Count; ++I) { + /* Get the insn referencing this label */ + CodeEntry* E = CollAt (&L->JumpFrom, I); + /* Remove the reference */ + E->JumpTo = 0; + } + CollDeleteAll (&L->JumpFrom); + + /* Remove the reference to the owning instruction */ + CollDeleteItem (&L->Owner->Labels, L); + + /* All references removed, delete the label itself */ + FreeCodeLabel (L); +} + + + void AddCodeSegHint (CodeSeg* S, unsigned Hint) /* Add a hint for the preceeding instruction */ { @@ -551,6 +606,16 @@ void OutputCodeSeg (FILE* F, const CodeSeg* S) /* Get the number of entries in this segment */ unsigned Count = CollCount (&S->Entries); + fprintf (F, "; Labels: "); + for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) { + const CodeLabel* L = S->LabelHash[I]; + while (L) { + fprintf (F, "%s ", L->Name); + L = L->Next; + } + } + fprintf (F, "\n"); + /* Output the segment directive */ fprintf (F, ".segment\t\"%s\"\n\n", S->SegName); @@ -633,19 +698,20 @@ void MergeCodeLabels (CodeSeg* S) unsigned RefCount = CollCount (&L->JumpFrom); for (K = 0; K < RefCount; ++K) { - /* Get the next instrcuction that references this label */ + /* Get the next instruction that references this label */ CodeEntry* E = CollAt (&L->JumpFrom, K); /* Change the reference */ CHECK (E->JumpTo == L); - E->JumpTo = RefLab; - CollAppend (&RefLab->JumpFrom, E); + AddLabelRef (RefLab, E); } + /* There are no more instructions jumping to this label now */ + CollDeleteAll (&L->JumpFrom); + /* Remove the label completely. */ - FreeCodeLabel (L); - CollDelete (&E->Labels, J); + DelCodeLabel (S, L); } /* The reference label is the only remaining label. Check if there @@ -654,9 +720,7 @@ void MergeCodeLabels (CodeSeg* S) */ if (CollCount (&RefLab->JumpFrom) == 0) { /* Delete the label */ - FreeCodeLabel (RefLab); - /* Remove it from the list */ - CollDelete (&E->Labels, 0); + DelCodeLabel (S, RefLab); } } } diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h index 37b7820bc..59bfb0842 100644 --- a/src/cc65/codeseg.h +++ b/src/cc65/codeseg.h @@ -95,9 +95,18 @@ CodeSeg* PopCodeSeg (void); void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3))); /* Add a line to the given code segment */ +void DelCodeSegLine (CodeSeg* S, unsigned Index); +/* Delete an entry from the code segment. This includes deleting any associated + * labels, removing references to labels and even removing the referenced labels + * if the reference count drops to zero. + */ + void AddCodeLabel (CodeSeg* S, const char* Name); /* Add a code label for the next instruction to follow */ +void DelCodeLabel (CodeSeg* S, CodeLabel* L); +/* Remove references from this label and delete it. */ + void AddCodeSegHint (CodeSeg* S, unsigned Hint); /* Add a hint for the preceeding instruction */ diff --git a/src/cc65/global.c b/src/cc65/global.c index 280a05d89..2a762f922 100644 --- a/src/cc65/global.c +++ b/src/cc65/global.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ +/* (C) 1998-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -47,6 +47,7 @@ unsigned char ANSI = 0; /* Strict ANSI flag */ unsigned char WriteableStrings = 0; /* Literal strings are r/w */ unsigned char NoWarn = 0; /* Suppress warnings */ unsigned char Optimize = 0; /* Optimize flag */ +unsigned long OptDisable = 0; /* Optimizer passes to disable */ unsigned char FavourSize = 1; /* Favour size over speed */ unsigned CodeSizeFactor = 100; /* Size factor for generated code */ unsigned char InlineStdFuncs = 0; /* Inline some known functions */ diff --git a/src/cc65/global.h b/src/cc65/global.h index 20a5e6a9d..27e839558 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2001 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -48,6 +48,7 @@ extern unsigned char ANSI; /* Strict ANSI flag */ extern unsigned char WriteableStrings; /* Literal strings are r/w */ extern unsigned char NoWarn; /* Suppress warnings */ extern unsigned char Optimize; /* Optimize flag */ +extern unsigned long OptDisable; /* Optimizer passes to disable */ extern unsigned char FavourSize; /* Favour size over speed */ extern unsigned CodeSizeFactor; /* Size factor for generated code */ extern unsigned char InlineStdFuncs; /* Inline some known functions */ diff --git a/src/cc65/main.c b/src/cc65/main.c index f1840a74d..6f3d0bbcf 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -567,11 +567,9 @@ int main (int argc, char* argv[]) P = Arg + 2; while (*P) { switch (*P++) { -#if 0 case 'f': sscanf (P, "%lx", (long*) &OptDisable); break; -#endif case 'i': FavourSize = 0; CodeSizeFactor = 200; diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index 5c9ba3a9f..8cca9cc6c 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -213,4 +213,22 @@ const OPCDesc* GetOPCDesc (opc_t OPC) +unsigned GetAMUseInfo (am_t AM) +/* Get usage info for the given addressing mode (addressing modes that use + * index registers return CI_USE... info for these registers). + */ +{ + /* Check the addressing mode. */ + switch (AM) { + case AM_ACC: return CI_USE_A; + case AM_ZPX: return CI_USE_X; + case AM_ABSX: return CI_USE_X; + case AM_ABSY: return CI_USE_Y; + case AM_ZPX_IND: return CI_USE_X; + case AM_ZP_INDY: return CI_USE_Y; + default: return CI_USE_NONE; + } +} + + diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index 5de93e0c6..aac583275 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -165,6 +165,11 @@ unsigned GetInsnSize (opc_t OPC, am_t AM); const OPCDesc* GetOPCDesc (opc_t OPC); /* Get an opcode description */ +unsigned GetAMUseInfo (am_t AM); +/* Get usage info for the given addressing mode (addressing modes that use + * index registers return CI_USE... info for these registers). + */ + /* End of opcodes.h */ -- 2.39.5