X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodeseg.c;h=adf023971a60b3f13b9181a239ca6d9a6ae61f0d;hb=84f85293f1662f30b44f5caf1fae2b5d5b8be0f7;hp=cb9664aebcabb6f91c0a847bd976b052a34fa816;hpb=f78237a6a67eae319b50df6cd34c32ed1f05b4d8;p=cc65 diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index cb9664aeb..adf023971 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -39,6 +39,7 @@ /* common */ #include "chartype.h" #include "check.h" +#include "global.h" #include "hashstr.h" #include "strutil.h" #include "xmalloc.h" @@ -155,7 +156,7 @@ static const char* SkipSpace (const char* S) static const char* ReadToken (const char* L, const char* Term, - char* Buf, unsigned BufSize) + char* Buf, unsigned BufSize) /* Read the next token into Buf, return the updated line pointer. The * token is terminated by one of the characters given in term. */ @@ -184,7 +185,7 @@ static const char* ReadToken (const char* L, const char* Term, -static CodeEntry* ParseInsn (CodeSeg* S, const char* L) +static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) /* Parse an instruction nnd generate a code entry from it. If the line contains * errors, output an error message and return NULL. * For simplicity, we don't accept the broad range of input a "real" assembler @@ -197,7 +198,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) am_t AM = 0; /* Initialize to keep gcc silent */ char Arg[64]; char Reg; - CodeEntry* E; + CodeEntry* E; CodeLabel* Label; /* Mnemonic */ @@ -296,8 +297,15 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) /* Absolute, maybe indexed */ L = ReadToken (L, ",", Arg, sizeof (Arg)); if (*L == '\0') { - /* Assume absolute */ - AM = AM_ABS; + /* Absolute, zeropage or branch */ + if ((OPC->Info & OF_BRA) != 0) { + /* Branch */ + AM = AM_BRA; + } else if (IsZPName (Arg)) { + AM = AM_ZP; + } else { + AM = AM_ABS; + } } else if (*L == ',') { /* Indexed */ L = SkipSpace (L+1); @@ -308,7 +316,11 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) Reg = toupper (*L); L = SkipSpace (L+1); if (Reg == 'X') { - AM = AM_ABSX; + if (IsZPName (Arg)) { + AM = AM_ZPX; + } else { + AM = AM_ABSX; + } } else if (Reg == 'Y') { AM = AM_ABSY; } else { @@ -329,18 +341,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) * if it does not exist. Ignore anything but local labels here. */ Label = 0; - if ((OPC->Info & OF_BRA) != 0 && Arg[0] == 'L') { - - unsigned Hash; - - /* Addressing mode must be alsobute or something is really wrong */ - CHECK (AM == AM_ABS); - - /* Addressing mode is a branch/jump */ - AM = AM_BRA; + if (AM == AM_BRA && Arg[0] == 'L') { /* Generate the hash over the label, then search for the label */ - Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE; + unsigned 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 */ @@ -353,7 +357,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) /* We do now have the addressing mode in AM. Allocate a new CodeEntry * structure and initialize it. */ - E = NewCodeEntry (OPC, AM, Arg, Label); + E = NewCodeEntry (OPC->OPC, AM, Arg, Label, LI); /* Return the new code entry */ return E; @@ -362,7 +366,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -393,13 +397,13 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func) S->ExitRegs = REG_NONE; } - /* Return the new struct */ + /* Return the new struct */ return S; } -void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap) +void AddCodeEntry (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap) /* Add a line to the given code segment */ { const char* L; @@ -432,7 +436,7 @@ void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap) break; default: - E = ParseInsn (S, L); + E = ParseInsn (S, LI, L); break; } @@ -527,10 +531,38 @@ void DelCodeEntry (CodeSeg* S, unsigned Index) -struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index) -/* Get an entry from the given code segment */ +void DelCodeEntries (CodeSeg* S, unsigned Start, unsigned Count) +/* Delete a range of code entries. This includes removing references to labels, + * labels attached to the entries and so on. + */ +{ + /* Start deleting the entries from the rear, because this involves less + * memory moving. + */ + while (Count--) { + DelCodeEntry (S, Start + Count); + } +} + + + +void MoveCodeEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos) +/* Move an entry from one position to another. OldPos is the current position + * of the entry, NewPos is the new position of the entry. + */ { - return CollAt (&S->Entries, Index); + /* Get the code entry and remove it from the collection */ + CodeEntry* E = GetCodeEntry (S, OldPos); + CollDelete (&S->Entries, OldPos); + + /* Correct NewPos if needed */ + if (NewPos >= OldPos) { + /* Position has changed with removal */ + --NewPos; + } + + /* Now insert it at the new position */ + CollInsert (&S->Entries, E, NewPos); } @@ -545,12 +577,34 @@ struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index) return 0; } else { /* Code entries left */ - return CollAt (&S->Entries, Index+1); + return CollAtUnchecked (&S->Entries, Index+1); } } +int GetCodeEntries (CodeSeg* S, struct CodeEntry** List, + unsigned Start, unsigned Count) +/* Get Count code entries into List starting at index start. Return true if + * we got the lines, return false if not enough lines were available. + */ +{ + /* Check if enough entries are available */ + if (Start + Count > CollCount (&S->Entries)) { + return 0; + } + + /* Copy the entries */ + while (Count--) { + *List++ = CollAtUnchecked (&S->Entries, Start++); + } + + /* We have the entries */ + return 1; +} + + + unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E) /* Return the index of a code entry */ { @@ -802,26 +856,6 @@ void MoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L) -void AddCodeSegHint (CodeSeg* S, unsigned Hint) -/* Add a hint for the preceeding instruction */ -{ - CodeEntry* E; - - /* Get the number of entries in this segment */ - unsigned EntryCount = GetCodeEntryCount (S); - - /* Must have at least one entry */ - CHECK (EntryCount > 0); - - /* Get the last entry */ - E = GetCodeEntry (S, EntryCount-1); - - /* Add the hint */ - E->Hints |= Hint; -} - - - void DelCodeSegAfter (CodeSeg* S, unsigned Last) /* Delete all entries including the given one */ { @@ -839,6 +873,16 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last) /* Check if this entry has a label reference */ if (E->JumpTo) { + /* If the label is a label in the label pool and this is the last + * reference to the label, remove the label from the pool. + */ + CodeLabel* L = E->JumpTo; + int Index = CollIndex (&S->Labels, L); + if (Index >= 0 && CollCount (&L->JumpFrom) == 1) { + /* Delete it from the pool */ + CollDelete (&S->Labels, Index); + } + /* Remove the reference to the label */ RemoveCodeLabelRef (S, E); } @@ -876,6 +920,7 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F) /* Output the code segment data to a file */ { unsigned I; + const LineInfo* LI; /* Get the number of entries in this segment */ unsigned Count = GetCodeEntryCount (S); @@ -893,20 +938,37 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F) fprintf (F, ".proc\t_%s\n\n", S->Func->Name); } - /* Output all entries */ + /* Output all entries, prepended by the line information if it has changed */ + LI = 0; for (I = 0; I < Count; ++I) { + /* Get the next entry */ + const CodeEntry* E = CollConstAt (&S->Entries, I); + /* Check if the line info has changed. If so, output the source line + * if the option is enabled and output debug line info if the debug + * option is enabled. + */ + if (E->LI != LI) { + /* Line info has changed, remember the new line info */ + LI = E->LI; - unsigned char Use; + /* Add the source line as a comment */ + if (AddSource) { + fprintf (F, ";\n; %s\n;\n", LI->Line); + } - OutputCodeEntry (CollConstAt (&S->Entries, I), F); + /* Add line debug info */ + if (DebugInfo) { + fprintf (F, "\t.dbg\tline, \"%s\", %u\n", + GetInputName (LI), GetInputLine (LI)); + } + } + /* Output the code */ + OutputCodeEntry (E, F); + } - /* Print usage info */ - Use = GetRegInfo ((CodeSeg*) S, I+1); - fprintf (F, - " Use: %c%c%c\n", - (Use & REG_A)? 'A' : '_', - (Use & REG_X)? 'X' : '_', - (Use & REG_Y)? 'Y' : '_'); + /* If debug info is enabled, terminate the last line number information */ + if (DebugInfo) { + fprintf (F, "\t.dbg\tline\n"); } /* If this is a segment for a function, leave the function */ @@ -917,11 +979,6 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F) -unsigned GetCodeEntryCount (const CodeSeg* S) -/* Return the number of entries for the given code segment */ -{ - return CollCount (&S->Entries); -}