From 09eed789dd6a76c0b049346c9573499490662e0c Mon Sep 17 00:00:00 2001 From: cuz Date: Wed, 16 May 2001 19:01:19 +0000 Subject: [PATCH] Working on the backend git-svn-id: svn://svn.cc65.org/cc65/trunk@729 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 55 +------- src/cc65/codeent.h | 57 +++++++- src/cc65/codeopt.c | 330 ++++++++++++++++++++++++++++++++++++++++++++- src/cc65/codeseg.c | 47 ++++--- src/cc65/codeseg.h | 25 +++- src/cc65/coptind.c | 55 +++++++- src/cc65/coptind.h | 5 +- src/cc65/opcodes.c | 174 +++++++++++------------- src/cc65/opcodes.h | 31 ++++- 9 files changed, 594 insertions(+), 185 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index e77041cd6..9a26f2deb 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -139,10 +139,13 @@ static int NumArg (const char* Arg, unsigned long* Num) -CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel* JumpTo) +CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo) /* Create a new code entry, initialize and return it */ { - /* Allocate memory */ + /* Get the opcode description */ + const OPCDesc* D = GetOPCDesc (OPC); + + /* Allocate memory */ CodeEntry* E = xmalloc (sizeof (CodeEntry)); /* Initialize the fields */ @@ -246,30 +249,6 @@ void AttachCodeLabel (CodeEntry* E, CodeLabel* L) -int CodeEntryHasLabel (const CodeEntry* E) -/* Check if the given code entry has labels attached */ -{ - return (CollCount (&E->Labels) > 0); -} - - - -unsigned GetCodeLabelCount (const CodeEntry* E) -/* Get the number of labels attached to this entry */ -{ - return CollCount (&E->Labels); -} - - - -CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index) -/* Get a label from this code entry */ -{ - return CollAt (&E->Labels, Index); -} - - - void MoveCodeLabel (CodeLabel* L, CodeEntry* E) /* Move the code label L from it's former owner to the code entry E. */ { @@ -283,30 +262,6 @@ void MoveCodeLabel (CodeLabel* L, CodeEntry* E) -int CodeEntryHasMark (const CodeEntry* E) -/* Return true if the given code entry has the CEF_USERMARK flag set */ -{ - return (E->Flags & CEF_USERMARK) != 0; -} - - - -void CodeEntrySetMark (CodeEntry* E) -/* Set the CEF_USERMARK flag for the given entry */ -{ - E->Flags |= CEF_USERMARK; -} - - - -void CodeEntryResetMark (CodeEntry* E) -/* Reset the CEF_USERMARK flag for the given entry */ -{ - E->Flags &= ~CEF_USERMARK; -} - - - void CodeEntrySetArg (CodeEntry* E, const char* Arg) /* Set a new argument for the given code entry. An old string is deleted. */ { diff --git a/src/cc65/codeent.h b/src/cc65/codeent.h index e862a197a..4c37eeb4f 100644 --- a/src/cc65/codeent.h +++ b/src/cc65/codeent.h @@ -42,6 +42,7 @@ /* common */ #include "coll.h" +#include "inline.h" /* cc65 */ #include "codelab.h" @@ -84,7 +85,7 @@ struct CodeEntry { -CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel* JumpTo); +CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo); /* Create a new code entry, initialize and return it */ void FreeCodeEntry (CodeEntry* E); @@ -101,26 +102,68 @@ int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2); void AttachCodeLabel (CodeEntry* E, CodeLabel* L); /* Attach the label to the entry */ -int CodeEntryHasLabel (const CodeEntry* E); +#if defined(HAVE_INLINE) +INLINE int CodeEntryHasLabel (const CodeEntry* E) /* Check if the given code entry has labels attached */ +{ + return (CollCount (&E->Labels) > 0); +} +#else +# define CodeEntryHasLabel(E) (CollCount (&(E)->Labels) > 0) +#endif -unsigned GetCodeLabelCount (const CodeEntry* E); +#if defined(HAVE_INLINE) +INLINE unsigned GetCodeLabelCount (const CodeEntry* E) /* Get the number of labels attached to this entry */ +{ + return CollCount (&E->Labels); +} +#else +# define GetCodeLabelCount(E) CollCount (&(E)->Labels) +#endif -CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index); +#if defined(HAVE_INLINE) +INLINE CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index) /* Get a label from this code entry */ +{ + return CollAt (&E->Labels, Index); +} +#else +# define GetCodeLabel(E, Index) CollAt (&(E)->Labels, (Index)) +#endif void MoveCodeLabel (CodeLabel* L, CodeEntry* E); /* Move the code label L from it's former owner to the code entry E. */ -int CodeEntryHasMark (const CodeEntry* E); +#if defined(HAVE_INLINE) +INLINE int CodeEntryHasMark (const CodeEntry* E) /* Return true if the given code entry has the CEF_USERMARK flag set */ +{ + return (E->Flags & CEF_USERMARK) != 0; +} +#else +# define CodeEntryHasMark(E) (((E)->Flags & CEF_USERMARK) != 0) +#endif -void CodeEntrySetMark (CodeEntry* E); +#if defined(HAVE_INLINE) +INLINE void CodeEntrySetMark (CodeEntry* E) /* Set the CEF_USERMARK flag for the given entry */ +{ + E->Flags |= CEF_USERMARK; +} +#else +# define CodeEntrySetMark(E) ((E)->Flags |= CEF_USERMARK) +#endif -void CodeEntryResetMark (CodeEntry* E); +#if defined(HAVE_INLINE) +INLINE void CodeEntryResetMark (CodeEntry* E) /* Reset the CEF_USERMARK flag for the given entry */ +{ + E->Flags &= ~CEF_USERMARK; +} +#else +# define CodeEntryResetMark(E) ((E)->Flags &= ~CEF_USERMARK) +#endif void CodeEntrySetArg (CodeEntry* E, const char* Arg); /* Set a new argument for the given code entry. An old string is deleted. */ diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index f6fc0c38e..06b5d3826 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -242,6 +242,322 @@ NextEntry: +/*****************************************************************************/ +/* nega optimizations */ +/*****************************************************************************/ + + + +static unsigned OptNegA1 (CodeSeg* S) +/* Check for + * + * ldx #$00 + * lda .. + * jsr bnega + * + * Remove the ldx if the lda does not use it. + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[2]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for a ldx */ + if (E->OPC == OPC_LDX && + E->AM == AM_IMM && + (E->Flags & CEF_NUMARG) != 0 && + E->Num == 0 && + GetCodeEntries (S, L, I+1, 2) && + L[0]->OPC == OPC_LDA && + (L[0]->Use & REG_X) == 0 && + L[1]->OPC == OPC_JSR && + strcmp (L[1]->Arg, "bnega") == 0) { + + /* Remove the ldx instruction */ + DelCodeEntry (S, I); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +static unsigned OptNegA2 (CodeSeg* S) +/* Check for + * + * lda .. + * jsr bnega + * jeq/jne .. + * + * Adjust the conditional branch and remove the call to the subroutine. + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[2]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OPC_LDA && + GetCodeEntries (S, L, I+1, 2) && + L[0]->OPC == OPC_JSR && + strcmp (L[0]->Arg, "bnega") == 0 && + !CodeEntryHasLabel (L[0]) && + (L[1]->Info & OF_ZBRA) != 0) { + + /* Invert the branch */ + ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC)); + + /* Delete the subroutine call */ + DelCodeEntry (S, I+1); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +/*****************************************************************************/ +/* negax optimizations */ +/*****************************************************************************/ + + + +static unsigned OptNegAX1 (CodeSeg* S) +/* Search for the sequence: + * + * lda (xx),y + * tax + * dey + * lda (xx),y + * jsr bnegax + * jne/jeq ... + * + * and replace it by + * + * lda (xx),y + * dey + * ora (xx),y + * jeq/jne ... + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[5]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OPC_LDA && + E->AM == AM_ZP_INDY && + GetCodeEntries (S, L, I+1, 5) && + L[0]->OPC == OPC_TAX && + L[1]->OPC == OPC_DEY && + L[2]->OPC == OPC_LDA && + L[2]->AM == AM_ZP_INDY && + strcmp (L[2]->Arg, E->Arg) == 0 && + !CodeEntryHasLabel (L[2]) && + L[3]->OPC == OPC_JSR && + strcmp (L[3]->Arg, "bnegax") == 0 && + !CodeEntryHasLabel (L[3]) && + (L[4]->Info & OF_ZBRA) != 0) { + + /* lda --> ora */ + ReplaceOPC (L[2], OPC_ORA); + + /* Invert the branch */ + ReplaceOPC (L[4], GetInverseBranch (L[4]->OPC)); + + /* Delete the entries no longer needed. Beware: Deleting entries + * will change the indices. + */ + DelCodeEntry (S, I+4); /* jsr bnegax */ + DelCodeEntry (S, I+1); /* tax */ + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +static unsigned OptNegAX2 (CodeSeg* S) +/* Search for the sequence: + * + * lda xx + * ldx yy + * jsr bnegax + * jne/jeq ... + * + * and replace it by + * + * lda xx + * ora xx+1 + * jeq/jne ... + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[3]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OPC_LDA && + GetCodeEntries (S, L, I+1, 3) && + L[0]->OPC == OPC_LDX && + !CodeEntryHasLabel (L[0]) && + L[1]->OPC == OPC_JSR && + strcmp (L[1]->Arg, "bnegax") == 0 && + !CodeEntryHasLabel (L[1]) && + (L[2]->Info & OF_ZBRA) != 0) { + + /* ldx --> ora */ + ReplaceOPC (L[0], OPC_ORA); + + /* Invert the branch */ + ReplaceOPC (L[2], GetInverseBranch (L[2]->OPC)); + + /* Delete the subroutine call */ + DelCodeEntry (S, I+2); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +static unsigned OptNegAX3 (CodeSeg* S) +/* Search for the sequence: + * + * jsr _xxx + * jsr bnega(x) + * jeq/jne ... + * + * and replace it by: + * + * jsr _xxx + * + * jne/jeq ... + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + CodeEntry* L[2]; + + /* Get next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OPC_JSR && + E->Arg[0] == '_' && + GetCodeEntries (S, L, I+1, 2) && + L[0]->OPC == OPC_JSR && + strncmp (L[0]->Arg,"bnega",5) == 0 && + !CodeEntryHasLabel (L[0]) && + (L[1]->Info & OF_ZBRA) != 0) { + + /* Check if we're calling bnega or bnegax */ + int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0); + + /* Delete the subroutine call */ + DelCodeEntry (S, I+1); + + /* Insert apropriate test code */ + if (ByteSized) { + /* Test bytes */ + InsertCodeEntry (S, NewCodeEntry (OPC_TAX, AM_IMP, 0, 0), I+1); + } else { + /* Test words */ + InsertCodeEntry (S, NewCodeEntry (OPC_STX, AM_ZP, "tmp1", 0), I+1); + InsertCodeEntry (S, NewCodeEntry (OPC_ORA, AM_ZP, "tmp1", 0), I+2); + } + + /* Invert the branch */ + ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC)); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -271,9 +587,21 @@ static OptFunc OptFuncs [] = { /* Optimize jump targets */ { OptJumpTarget, "OptJumpTarget", 0 }, /* Optimize conditional branches */ - { OptCondBranches, "OptCondBranches", 0 }, + { OptCondBranches, "OptCondBranches", 0 }, + /* Replace jumps to RTS by RTS */ + { OptRTSJumps, "OptRTSJumps", 0 }, /* Remove calls to the bool transformer subroutines */ { OptBoolTransforms, "OptBoolTransforms", 0 }, + /* Optimize calls to nega */ + { OptNegA1, "OptNegA1", 0 }, + /* Optimize calls to nega */ + { OptNegA2, "OptNegA2", 0 }, + /* Optimize calls to negax */ + { OptNegAX1, "OptNegAX1", 0 }, + /* Optimize calls to negax */ + { OptNegAX2, "OptNegAX2", 0 }, + /* Optimize calls to negax */ + { OptNegAX3, "OptNegAX3", 0 }, /* Remove unused loads */ { OptUnusedLoads, "OptUnusedLoads", 0 }, /* Optimize branch distance */ diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index cb9664aeb..8cf8bb070 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -155,7 +155,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. */ @@ -181,7 +181,7 @@ static const char* ReadToken (const char* L, const char* Term, /* Return the updated line pointer */ return L; } - + static CodeEntry* ParseInsn (CodeSeg* S, const char* L) @@ -197,7 +197,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 */ @@ -353,7 +353,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); /* Return the new code entry */ return E; @@ -393,7 +393,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func) S->ExitRegs = REG_NONE; } - /* Return the new struct */ + /* Return the new struct */ return S; } @@ -527,14 +527,6 @@ void DelCodeEntry (CodeSeg* S, unsigned Index) -struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index) -/* Get an entry from the given code segment */ -{ - return CollAt (&S->Entries, Index); -} - - - struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index) /* Get the code entry following the one with the index Index. If there is no * following code entry, return NULL. @@ -545,12 +537,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 */ { @@ -917,11 +931,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); -} diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h index 7904baa15..dd9105c3a 100644 --- a/src/cc65/codeseg.h +++ b/src/cc65/codeseg.h @@ -44,6 +44,7 @@ /* common */ #include "attrib.h" #include "coll.h" +#include "inline.h" /* cc65 */ #include "codelab.h" @@ -106,14 +107,27 @@ void DelCodeEntry (CodeSeg* S, unsigned Index); * if the reference count drops to zero. */ -struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index); +#if defined(HAVE_INLINE) +INLINE struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index) /* Get an entry from the given code segment */ +{ + return CollAt (&S->Entries, Index); +} +#else +# define GetCodeEntry(S, Index) CollAt(&(S)->Entries, (Index)) +#endif struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index); /* Get the code entry following the one with the index Index. If there is no * following code entry, return NULL. */ +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. + */ + unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E); /* Return the index of a code entry */ @@ -162,8 +176,15 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last); void OutputCodeSeg (const CodeSeg* S, FILE* F); /* Output the code segment data to a file */ -unsigned GetCodeEntryCount (const CodeSeg* S); +#if defined(HAVE_INLINE) +INLINE unsigned GetCodeEntryCount (const CodeSeg* S) /* Return the number of entries for the given code segment */ +{ + return CollCount (&S->Entries); +} +#else +# define GetCodeEntryCount(S) CollCount (&(S)->Entries) +#endif diff --git a/src/cc65/coptind.c b/src/cc65/coptind.c index 7843967db..5e263a8dc 100644 --- a/src/cc65/coptind.c +++ b/src/cc65/coptind.c @@ -44,6 +44,51 @@ +/*****************************************************************************/ +/* Replace jumps to RTS by RTS */ +/*****************************************************************************/ + + + +unsigned OptRTSJumps (CodeSeg* S) +/* Replace jumps to RTS by RTS */ +{ + unsigned Changes = 0; + + /* Walk over all entries minus the last one */ + unsigned I = 0; + while (I < GetCodeEntryCount (S)) { + + /* Get the next entry */ + CodeEntry* E = GetCodeEntry (S, I); + + /* Check if it's an unconditional branch to a local target */ + if ((E->Info & OF_UBRA) != 0 && + E->JumpTo != 0 && + E->JumpTo->Owner->OPC == OPC_RTS) { + + /* Delete the jump */ + DelCodeEntry (S, I); + + /* Insert an RTS instruction instead */ + InsertCodeEntry (S, NewCodeEntry (OPC_RTS, AM_IMP, 0, 0), I); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + /*****************************************************************************/ /* Remove dead jumps */ /*****************************************************************************/ @@ -118,9 +163,11 @@ unsigned OptDeadCode (CodeSeg* S) return 0; } - /* Walk over all entries minus the last one */ + /* Walk over all entries */ I = 0; - while (I < Count-1) { + while (I < Count) { + + CodeEntry* N; /* Get this entry */ CodeEntry* E = GetCodeEntry (S, I); @@ -128,7 +175,9 @@ unsigned OptDeadCode (CodeSeg* S) /* Check if it's an unconditional branch, and if the next entry has * no labels attached */ - if ((E->Info & OF_DEAD) != 0 && !CodeEntryHasLabel (GetCodeEntry (S, I+1))) { + if ((E->Info & OF_DEAD) != 0 && + (N = GetNextCodeEntry (S, I)) != 0 && + !CodeEntryHasLabel (N)) { /* Delete the next entry */ DelCodeEntry (S, I+1); diff --git a/src/cc65/coptind.h b/src/cc65/coptind.h index bf67a20eb..d0afc5c0f 100644 --- a/src/cc65/coptind.h +++ b/src/cc65/coptind.h @@ -48,7 +48,10 @@ -unsigned OptDeadJumps (CodeSeg* S); +unsigned OptRTSJumps (CodeSeg* S); +/* Replace jumps to RTS by RTS */ + +unsigned OptDeadJumps (CodeSeg* S); /* Remove dead jumps (jumps to the next instruction) */ unsigned OptDeadCode (CodeSeg* S); diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index 476f674f4..b9e519036 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -54,81 +54,81 @@ -/* Mapper table, mnemonic --> opcode */ -static const OPCDesc OPCTable[OPC_COUNT] = { - { OPC_ADC, "adc", 0, REG_A, REG_A, OF_NONE }, - { OPC_AND, "and", 0, REG_A, REG_A, OF_NONE }, - { OPC_ASL, "asl", 0, REG_A, REG_A, OF_NONE }, - { OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_BIT, "bit", 0, REG_A, REG_NONE, OF_NONE }, - { OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA }, - { OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA }, - { OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_CMP, "cmp", 0, REG_A, REG_NONE, OF_NONE }, - { OPC_CPX, "cpx", 0, REG_X, REG_NONE, OF_NONE }, - { OPC_CPY, "cpy", 0, REG_Y, REG_NONE, OF_NONE }, - { OPC_DEA, "dea", 1, REG_A, REG_A, OF_NONE }, - { OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE }, - { OPC_DEX, "dex", 1, REG_X, REG_X, OF_NONE }, - { OPC_DEY, "dey", 1, REG_Y, REG_Y, OF_NONE }, - { OPC_EOR, "eor", 0, REG_A, REG_A, OF_NONE }, - { OPC_INA, "ina", 1, REG_A, REG_A, OF_NONE }, - { OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE }, - { OPC_INX, "inx", 1, REG_X, REG_X, OF_NONE }, - { OPC_INY, "iny", 1, REG_Y, REG_Y, OF_NONE }, - { OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA }, - { OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE }, - { OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, - { OPC_LDA, "lda", 0, REG_NONE, REG_A, OF_LOAD }, - { OPC_LDX, "ldx", 0, REG_NONE, REG_X, OF_LOAD }, - { OPC_LDY, "ldy", 0, REG_NONE, REG_Y, OF_LOAD }, - { OPC_LSR, "lsr", 0, REG_A, REG_A, OF_NONE }, - { OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_ORA, "ora", 0, REG_A, REG_A, OF_NONE }, - { OPC_PHA, "pha", 1, REG_A, REG_NONE, OF_NONE }, - { OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_PHX, "phx", 1, REG_X, REG_NONE, OF_NONE }, - { OPC_PHY, "phy", 1, REG_Y, REG_NONE, OF_NONE }, - { OPC_PLA, "pla", 1, REG_NONE, REG_A, OF_NONE }, - { OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_PLX, "plx", 1, REG_NONE, REG_X, OF_NONE }, - { OPC_PLY, "ply", 1, REG_NONE, REG_Y, OF_NONE }, - { OPC_ROL, "rol", 0, REG_A, REG_A, OF_NONE }, - { OPC_ROR, "ror", 0, REG_A, REG_A, OF_NONE }, - { OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET }, - { OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET }, - { OPC_SBC, "sbc", 0, REG_A, REG_A, OF_NONE }, - { OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE }, - { OPC_STA, "sta", 0, REG_A, REG_NONE, OF_NONE }, - { OPC_STX, "stx", 0, REG_X, REG_NONE, OF_NONE }, - { OPC_STY, "sty", 0, REG_Y, REG_NONE, OF_NONE }, - { OPC_TAX, "tax", 1, REG_A, REG_X, OF_NONE }, - { OPC_TAY, "tay", 1, REG_A, REG_Y, OF_NONE }, - { OPC_TRB, "trb", 0, REG_A, REG_NONE, OF_NONE }, - { OPC_TSB, "tsb", 0, REG_A, REG_NONE, OF_NONE }, - { OPC_TSX, "tsx", 1, REG_NONE, REG_X, OF_NONE }, - { OPC_TXA, "txa", 1, REG_X, REG_A, OF_NONE }, - { OPC_TXS, "txs", 1, REG_X, REG_NONE, OF_NONE }, - { OPC_TYA, "tya", 1, REG_A, REG_A, OF_NONE }, +/* Opcode description table */ +const OPCDesc OPCTable[OPC_COUNT] = { + { OPC_ADC, "adc", 0, REG_A, REG_A, OF_NONE }, + { OPC_AND, "and", 0, REG_A, REG_A, OF_NONE }, + { OPC_ASL, "asl", 0, REG_A, REG_A, OF_NONE }, + { OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA }, + { OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA }, + { OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA }, + { OPC_BIT, "bit", 0, REG_A, REG_NONE, OF_NONE }, + { OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA }, + { OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA }, + { OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA }, + { OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA }, + { OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA }, + { OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA }, + { OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_CMP, "cmp", 0, REG_A, REG_NONE, OF_NONE }, + { OPC_CPX, "cpx", 0, REG_X, REG_NONE, OF_NONE }, + { OPC_CPY, "cpy", 0, REG_Y, REG_NONE, OF_NONE }, + { OPC_DEA, "dea", 1, REG_A, REG_A, OF_NONE }, + { OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE }, + { OPC_DEX, "dex", 1, REG_X, REG_X, OF_NONE }, + { OPC_DEY, "dey", 1, REG_Y, REG_Y, OF_NONE }, + { OPC_EOR, "eor", 0, REG_A, REG_A, OF_NONE }, + { OPC_INA, "ina", 1, REG_A, REG_A, OF_NONE }, + { OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE }, + { OPC_INX, "inx", 1, REG_X, REG_X, OF_NONE }, + { OPC_INY, "iny", 1, REG_Y, REG_Y, OF_NONE }, + { OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, + { OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, + { OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA }, + { OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, + { OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA }, + { OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA }, + { OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, + { OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE }, + { OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, + { OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA }, + { OPC_LDA, "lda", 0, REG_NONE, REG_A, OF_LOAD }, + { OPC_LDX, "ldx", 0, REG_NONE, REG_X, OF_LOAD }, + { OPC_LDY, "ldy", 0, REG_NONE, REG_Y, OF_LOAD }, + { OPC_LSR, "lsr", 0, REG_A, REG_A, OF_NONE }, + { OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_ORA, "ora", 0, REG_A, REG_A, OF_NONE }, + { OPC_PHA, "pha", 1, REG_A, REG_NONE, OF_NONE }, + { OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_PHX, "phx", 1, REG_X, REG_NONE, OF_NONE }, + { OPC_PHY, "phy", 1, REG_Y, REG_NONE, OF_NONE }, + { OPC_PLA, "pla", 1, REG_NONE, REG_A, OF_NONE }, + { OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_PLX, "plx", 1, REG_NONE, REG_X, OF_NONE }, + { OPC_PLY, "ply", 1, REG_NONE, REG_Y, OF_NONE }, + { OPC_ROL, "rol", 0, REG_A, REG_A, OF_NONE }, + { OPC_ROR, "ror", 0, REG_A, REG_A, OF_NONE }, + { OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET }, + { OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET }, + { OPC_SBC, "sbc", 0, REG_A, REG_A, OF_NONE }, + { OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE }, + { OPC_STA, "sta", 0, REG_A, REG_NONE, OF_NONE }, + { OPC_STX, "stx", 0, REG_X, REG_NONE, OF_NONE }, + { OPC_STY, "sty", 0, REG_Y, REG_NONE, OF_NONE }, + { OPC_TAX, "tax", 1, REG_A, REG_X, OF_NONE }, + { OPC_TAY, "tay", 1, REG_A, REG_Y, OF_NONE }, + { OPC_TRB, "trb", 0, REG_A, REG_NONE, OF_NONE }, + { OPC_TSB, "tsb", 0, REG_A, REG_NONE, OF_NONE }, + { OPC_TSX, "tsx", 1, REG_NONE, REG_X, OF_NONE }, + { OPC_TXA, "txa", 1, REG_X, REG_A, OF_NONE }, + { OPC_TXS, "txs", 1, REG_X, REG_NONE, OF_NONE }, + { OPC_TYA, "tya", 1, REG_A, REG_A, OF_NONE }, }; @@ -203,30 +203,6 @@ unsigned GetInsnSize (opc_t OPC, am_t AM) -const OPCDesc* GetOPCDesc (opc_t OPC) -/* Get an opcode description */ -{ - /* Check the range */ - PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT); - - /* Return the description */ - return &OPCTable [OPC]; -} - - - -unsigned char GetOPCInfo (opc_t OPC) -/* Get opcode information */ -{ - /* Check the range */ - PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT); - - /* Return the info */ - return OPCTable[OPC].Info; -} - - - unsigned char GetAMUseInfo (am_t AM) /* Get usage info for the given addressing mode (addressing modes that use * index registers return REG_r info for these registers). diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index c4898b091..b9d297f90 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -38,6 +38,11 @@ +/* common */ +#include "inline.h" + + + /*****************************************************************************/ /* Data */ /*****************************************************************************/ @@ -155,7 +160,8 @@ typedef enum { #define OF_NONE 0x0000U /* No additional information */ #define OF_UBRA 0x0001U /* Unconditional branch */ #define OF_CBRA 0x0002U /* Conditional branch */ -#define OF_LBRA 0x0004U /* Jump/branch is long */ +#define OF_ZBRA 0x0004U /* Branch on zero flag condition */ +#define OF_LBRA 0x0008U /* Jump/branch is long */ #define OF_RET 0x0010U /* Return from function */ #define OF_LOAD 0x0020U /* Register load */ #define OF_BRA (OF_UBRA|OF_CBRA) /* Operation is a jump/branch */ @@ -171,6 +177,9 @@ typedef struct { unsigned char Info; /* Additional information */ } OPCDesc; +/* Opcode description table */ +extern const OPCDesc OPCTable[OPC_COUNT]; + /*****************************************************************************/ @@ -187,11 +196,27 @@ const OPCDesc* FindOpcode (const char* OPC); unsigned GetInsnSize (opc_t OPC, am_t AM); /* Return the size of the given instruction */ -const OPCDesc* GetOPCDesc (opc_t OPC); +#if defined(HAVE_INLINE) +INLINE const OPCDesc* GetOPCDesc (opc_t OPC) /* Get an opcode description */ +{ + /* Return the description */ + return &OPCTable [OPC]; +} +#else +# define GetOPCDesc(OPC) (&OPCTable [(OPC)]) +#endif -unsigned char GetOPCInfo (opc_t OPC); +#if defined(HAVE_INLINE) +INLINE unsigned char GetOPCInfo (opc_t OPC) /* Get opcode information */ +{ + /* Return the info */ + return OPCTable[OPC].Info; +} +#else +# define GetOPCInfo(OPC) (OPCTable[(OPC)].Info) +#endif unsigned char GetAMUseInfo (am_t AM); /* Get usage info for the given addressing mode (addressing modes that use