From 88792854a61000c177dc86fe414bd8bb96d76a5b Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 1 May 2001 15:50:31 +0000 Subject: [PATCH] Working on the new backend git-svn-id: svn://svn.cc65.org/cc65/trunk@701 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codegen.c | 4 +- src/cc65/codelab.c | 1 + src/cc65/codelab.h | 9 +- src/cc65/codeseg.c | 189 ++++++++++++++++++++++++++---------------- src/cc65/codeseg.h | 11 ++- src/cc65/make/gcc.mak | 12 ++- src/cc65/opcodes.c | 151 +++++++++++++++++---------------- src/cc65/opcodes.h | 11 ++- 8 files changed, 235 insertions(+), 153 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 7d7c0b569..8c1bd89f5 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -391,7 +391,7 @@ void g_defloclabel (unsigned label) /* Define a local label */ { if (CurSeg == SEG_CODE) { - AddCodeSegLabel (CS, LocalLabelName (label)); + AddLocCodeLabel (CS, LocalLabelName (label)); } else { AddDataSegLine (DS, "%s:", LocalLabelName (label)); } @@ -412,7 +412,7 @@ void g_defgloblabel (const char* Name) /* ##### */ char Buf[64]; xsprintf (Buf, sizeof (Buf), "_%s", Name); - AddCodeSegLabel (CS, Buf); + AddExtCodeLabel (CS, Buf); } else { AddDataSegLine (DS, "_%s:", Name); } diff --git a/src/cc65/codelab.c b/src/cc65/codelab.c index 823f2eb70..46c43559a 100644 --- a/src/cc65/codelab.c +++ b/src/cc65/codelab.c @@ -57,6 +57,7 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash) L->Next = 0; L->Name = xstrdup (Name); L->Hash = Hash; + L->Flags = 0; L->Owner = 0; InitCollection (&L->JumpFrom); diff --git a/src/cc65/codelab.h b/src/cc65/codelab.h index 8fb3143e2..e77873abe 100644 --- a/src/cc65/codelab.h +++ b/src/cc65/codelab.h @@ -51,12 +51,17 @@ +/* Label flags, bitmapped */ +#define LF_DEF 0x0001U /* Label was defined */ +#define LF_EXT 0x0002U /* Label is external */ + /* Label structure */ typedef struct CodeLabel CodeLabel; struct CodeLabel { CodeLabel* Next; /* Next in hash list */ char* Name; /* Label name */ - unsigned Hash; /* Hash over the name */ + unsigned short Hash; /* Hash over the name */ + unsigned short Flags; /* Flag flags */ struct CodeEntry* Owner; /* Owner entry */ Collection JumpFrom; /* Entries that jump here */ }; @@ -64,7 +69,7 @@ struct CodeLabel { /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index 06fea6e36..c3993237c 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -233,7 +233,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L) /* Indexed */ L = SkipSpace (L+1); if (*L == '\0') { - Error ("ASM code error: syntax error"); + Error ("ASM code error: syntax error"); return 0; } else { Reg = toupper (*L); @@ -390,23 +390,30 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...) if (E) { /* Transfer the labels if we have any */ - unsigned LabelCount = CollCount (&S->Labels); unsigned I; + unsigned LabelCount = CollCount (&S->Labels); for (I = 0; I < LabelCount; ++I) { - CollAppend (&E->Labels, CollAt (&S->Labels, I)); + /* Get the label */ + CodeLabel* L = CollAt (&S->Labels, I); + /* Mark it as defined */ + L->Flags |= LF_DEF; + /* Move it to the code entry */ + CollAppend (&E->Labels, L); } + + /* Delete the transfered labels */ CollDeleteAll (&S->Labels); /* Add the entry to the list of code entries in this segment */ - CollAppend (&S->Entries, E); + CollAppend (&S->Entries, E); } } -void AddCodeSegLabel (CodeSeg* S, const char* Name) -/* Add a label for the next instruction to follow */ +CodeLabel* AddCodeLabel (CodeSeg* S, const char* Name) +/* Add a code label for the next instruction to follow */ { /* Calculate the hash from the name */ unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE; @@ -425,6 +432,30 @@ void AddCodeSegLabel (CodeSeg* S, const char* Name) /* We do now have a valid label. Remember it for later */ CollAppend (&S->Labels, L); + + /* Return the label */ + return L; +} + + + +void AddExtCodeLabel (CodeSeg* S, const char* Name) +/* Add an external code label for the next instruction to follow */ +{ + /* Add the code label */ + CodeLabel* L = AddCodeLabel (S, Name); + + /* Mark it as external label */ + L->Flags |= LF_EXT; +} + + + +void AddLocCodeLabel (CodeSeg* S, const char* Name) +/* Add a local code label for the next instruction to follow */ +{ + /* Add the code label */ + AddCodeLabel (S, Name); } @@ -450,23 +481,34 @@ void AddCodeSegHint (CodeSeg* S, unsigned Hint) void DelCodeSegAfter (CodeSeg* S, unsigned Last) -/* Delete all entries after the given one */ +/* Delete all entries including the given one */ { - unsigned I; - /* Get the number of entries in this segment */ unsigned Count = CollCount (&S->Entries); - /* ### We need some more cleanup here wrt labels */ + /* Must not be called with count zero */ + CHECK (Count > 0 && Count >= Last); /* Remove all entries after the given one */ - for (I = Count-1; I > Last; --I) { - FreeCodeEntry (CollAt (&S->Entries, I)); - CollDelete (&S->Entries, I); - } + while (Last < Count) { + + /* Get the next entry */ + CodeEntry* E = CollAt (&S->Entries, Count-1); + + /* We have to transfer all labels to the code segment label pool */ + unsigned LabelCount = CollCount (&E->Labels); + while (LabelCount--) { + CodeLabel* L = CollAt (&E->Labels, LabelCount); + L->Flags &= ~LF_DEF; + CollAppend (&S->Labels, L); + } + CollDeleteAll (&E->Labels); - /* Delete all waiting labels */ - CollDeleteAll (&S->Labels); + /* Remove the code entry */ + FreeCodeEntry (CollAt (&S->Entries, Count-1)); + CollDelete (&S->Entries, Count-1); + --Count; + } } @@ -501,7 +543,7 @@ CodeLabel* FindCodeLabel (CodeSeg* S, const char* Name, unsigned Hash) if (strcmp (Name, L->Name) == 0) { /* Found */ break; - } + } L = L->Next; } return L; @@ -526,63 +568,68 @@ void MergeCodeLabels (CodeSeg* S) /* Get a pointer to the next entry */ CodeEntry* E = CollAt (&S->Entries, I); - /* If this entry has zero labels, continue with the next one */ - unsigned LabelCount = CollCount (&E->Labels); - if (LabelCount == 0) { - continue; - } - - /* We have at least one label. Use the first one as reference label. - * We don't have a notification for global labels for now, and using - * the first one will also keep the global function labels, since these - * are inserted at position 0. - */ - RefLab = CollAt (&E->Labels, 0); - - /* Walk through the remaining labels and change references to these - * labels to a reference to the one and only label. Delete the labels - * that are no longer used. To increase performance, walk backwards - * through the list. - */ - for (J = LabelCount-1; J >= 1; --J) { - - unsigned K; - - /* Get the next label */ - CodeLabel* L = CollAt (&E->Labels, J); - - /* Walk through all instructions referencing this label */ - unsigned RefCount = CollCount (&L->JumpFrom); - for (K = 0; K < RefCount; ++K) { - - /* Get the next instrcuction that references this label */ - CodeEntry* E = CollAt (&L->JumpFrom, K); - - /* Change the reference */ - CHECK (E->JumpTo == L); - E->JumpTo = RefLab; - CollAppend (&RefLab->JumpFrom, E); - - } - - /* Delete the label */ - FreeCodeLabel (L); - - /* Remove it from the list */ - CollDelete (&E->Labels, J); - + /* If this entry has zero labels, continue with the next one */ + unsigned LabelCount = CollCount (&E->Labels); + if (LabelCount == 0) { + continue; + } + + /* We have at least one label. Use the first one as reference label. + * We don't have a notification for global labels for now, and using + * the first one will also keep the global function labels, since these + * are inserted at position 0. + */ + RefLab = CollAt (&E->Labels, 0); + + /* Walk through the remaining labels and change references to these + * labels to a reference to the one and only label. Delete the labels + * that are no longer used. To increase performance, walk backwards + * through the list. + */ + for (J = LabelCount-1; J >= 1; --J) { + + unsigned K; + + /* Get the next label */ + CodeLabel* L = CollAt (&E->Labels, J); + + /* Walk through all instructions referencing this label */ + unsigned RefCount = CollCount (&L->JumpFrom); + for (K = 0; K < RefCount; ++K) { + + /* Get the next instrcuction that references this label */ + CodeEntry* E = CollAt (&L->JumpFrom, K); + + /* Change the reference */ + CHECK (E->JumpTo == L); + E->JumpTo = RefLab; + CollAppend (&RefLab->JumpFrom, E); + + } + + /* If the label is not an external label, we may remove the + * label completely. + */ +#if 0 + if ((L->Flags & LF_EXT) == 0) { + FreeCodeLabel (L); + CollDelete (&E->Labels, J); + } +#endif } - /* The reference label is the only remaining label. Check if there - * are any references to this label, and delete it if this is not - * the case. + /* The reference label is the only remaining label. If it is not an + * external label, check if there are any references to this label, + * and delete it if this is not the case. */ - if (CollCount (&RefLab->JumpFrom) == 0) { - /* Delete the label */ - FreeCodeLabel (RefLab); - /* Remove it from the list */ - CollDelete (&E->Labels, 0); - } +#if 0 + if ((RefLab->Flags & LF_EXT) == 0 && CollCount (&RefLab->JumpFrom) == 0) { + /* Delete the label */ + FreeCodeLabel (RefLab); + /* Remove it from the list */ + CollDelete (&E->Labels, 0); + } +#endif } } diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h index 524739adc..0279165d3 100644 --- a/src/cc65/codeseg.h +++ b/src/cc65/codeseg.h @@ -84,14 +84,17 @@ void FreeCodeSeg (CodeSeg* S); void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3))); /* Add a line to the given code segment */ -void AddCodeSegLabel (CodeSeg* S, const char* Name); -/* Add a label for the next instruction to follow */ +void AddExtCodeLabel (CodeSeg* S, const char* Name); +/* Add an external code label for the next instruction to follow */ + +void AddLocCodeLabel (CodeSeg* S, const char* Name); +/* Add a local code label for the next instruction to follow */ void AddCodeSegHint (CodeSeg* S, unsigned Hint); /* Add a hint for the preceeding instruction */ void DelCodeSegAfter (CodeSeg* S, unsigned Last); -/* Delete all entries after the given one */ +/* Delete all entries including the given one */ void OutputCodeSeg (FILE* F, const CodeSeg* S); /* Output the code segment data to a file */ @@ -106,7 +109,7 @@ void MergeCodeLabels (CodeSeg* S); unsigned GetCodeSegEntries (const CodeSeg* S); /* Return the number of entries for the given code segment */ - + /* End of codeseg.h */ diff --git a/src/cc65/make/gcc.mak b/src/cc65/make/gcc.mak index dada08c27..a490d8dce 100644 --- a/src/cc65/make/gcc.mak +++ b/src/cc65/make/gcc.mak @@ -39,7 +39,7 @@ OBJS = anonname.o \ funcdesc.o \ function.o \ global.o \ - goto.o \ + goto.o \ ident.o \ incpath.o \ input.o \ @@ -60,7 +60,7 @@ OBJS = anonname.o \ util.o LIBS = $(B6502)/b6502.a \ - $(COMMON)/common.a + $(COMMON)/common.a # ------------------------------------------------------------------------------ @@ -76,10 +76,16 @@ all: depend @$(MAKE) -f make/gcc.mak all endif -$(EXE): $(OBJS) $(LIBS) +$(EXE): $(OBJS) $(LIBS) subs $(CC) $(LDFLAGS) -o $(EXE) $(CFLAGS) $(OBJS) $(LIBS) @if [ $(OS2_SHELL) ] ; then $(EBIND) $(EXE) ; fi +.PHONY: subs +subs: + @for dir in $(COMMON) $(B6502); do \ + $(MAKE) -C $$dir -f make/gcc.mak || exit 1; \ + done + clean: rm -f *~ core *.map diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index 9974e5f90..6dd6cf409 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -54,77 +54,85 @@ /* Mapper table, mnemonic --> opcode */ static const OPCDesc OPCTable[OPC_COUNT] = { - { "adc", OPC_ADC, CI_USE_A | CI_CHG_A }, - { "and", OPC_AND, CI_USE_A | CI_CHG_A }, - { "asl", OPC_ASL, CI_USE_A | CI_CHG_A }, - { "bcc", OPC_BCC, CI_BRA }, - { "bcs", OPC_BCS, CI_BRA }, - { "beq", OPC_BEQ, CI_BRA }, - { "bit", OPC_BIT, CI_USE_A }, - { "bmi", OPC_BMI, CI_BRA }, - { "bne", OPC_BNE, CI_BRA }, - { "bpl", OPC_BPL, CI_BRA }, - { "bra", OPC_BRA, CI_BRA }, - { "brk", OPC_BRK, CI_BRA }, - { "bvc", OPC_BVC, CI_BRA }, - { "bvs", OPC_BVS, CI_BRA }, - { "clc", OPC_CLC, CI_CHG_NONE }, - { "cld", OPC_CLD, CI_CHG_NONE }, - { "cli", OPC_CLI, CI_CHG_NONE }, - { "clv", OPC_CLV, CI_CHG_NONE }, - { "cmp", OPC_CMP, CI_USE_A }, - { "cpx", OPC_CPX, CI_USE_X }, - { "cpy", OPC_CPY, CI_USE_Y }, - { "dea", OPC_DEA, CI_USE_A | CI_CHG_A }, - { "dec", OPC_DEC, CI_NONE }, - { "dex", OPC_DEX, CI_USE_X | CI_CHG_X }, - { "dey", OPC_DEY, CI_USE_Y | CI_CHG_Y }, - { "eor", OPC_EOR, CI_USE_A | CI_CHG_A }, - { "ina", OPC_INA, CI_USE_A | CI_CHG_A }, - { "inc", OPC_INC, CI_NONE }, - { "inx", OPC_INX, CI_USE_X | CI_CHG_X }, - { "iny", OPC_INY, CI_USE_Y | CI_CHG_Y }, - { "jmp", OPC_JMP, CI_BRA }, - { "jsr", OPC_JSR, CI_BRA }, - { "lda", OPC_LDA, CI_CHG_A }, - { "ldx", OPC_LDX, CI_CHG_X }, - { "ldy", OPC_LDY, CI_CHG_Y }, - { "lsr", OPC_LSR, CI_USE_A | CI_CHG_A }, - { "nop", OPC_NOP, CI_NONE }, - { "ora", OPC_ORA, CI_USE_A | CI_CHG_A }, - { "pha", OPC_PHA, CI_USE_A }, - { "php", OPC_PHP, CI_NONE }, - { "phx", OPC_PHX, CI_USE_X }, - { "phy", OPC_PHY, CI_USE_Y }, - { "pla", OPC_PLA, CI_CHG_A }, - { "plp", OPC_PLP, CI_NONE }, - { "plx", OPC_PLX, CI_CHG_X }, - { "ply", OPC_PLY, CI_CHG_Y }, - { "rol", OPC_ROL, CI_USE_A | CI_CHG_A }, - { "ror", OPC_ROR, CI_USE_A | CI_CHG_A }, - { "rti", OPC_RTI, CI_NONE }, - { "rts", OPC_RTS, CI_NONE }, - { "sbc", OPC_SBC, CI_USE_A | CI_CHG_A }, - { "sec", OPC_SEC, CI_NONE }, - { "sed", OPC_SED, CI_NONE }, - { "sei", OPC_SEI, CI_NONE }, - { "sta", OPC_STA, CI_USE_A }, - { "stx", OPC_STX, CI_USE_X }, - { "sty", OPC_STY, CI_USE_Y }, - { "tax", OPC_TAX, CI_USE_A | CI_CHG_X }, - { "tay", OPC_TAY, CI_USE_A | CI_CHG_Y }, - { "trb", OPC_TRB, CI_USE_A }, - { "tsb", OPC_TSB, CI_USE_A }, - { "tsx", OPC_TSX, CI_CHG_X }, - { "txa", OPC_TXA, CI_USE_X | CI_CHG_A }, - { "txs", OPC_TXS, CI_USE_X }, - { "tya", OPC_TYA, CI_USE_Y | CI_CHG_A } + { "adc", OPC_ADC, 0, CI_USE_A | CI_CHG_A }, + { "and", OPC_AND, 0, CI_USE_A | CI_CHG_A }, + { "asl", OPC_ASL, 0, CI_USE_A | CI_CHG_A }, + { "bcc", OPC_BCC, 2, CI_BRA }, + { "bcs", OPC_BCS, 2, CI_BRA }, + { "beq", OPC_BEQ, 2, CI_BRA }, + { "bit", OPC_BIT, 0, CI_USE_A }, + { "bmi", OPC_BMI, 2, CI_BRA }, + { "bne", OPC_BNE, 2, CI_BRA }, + { "bpl", OPC_BPL, 2, CI_BRA }, + { "bra", OPC_BRA, 2, CI_BRA }, + { "brk", OPC_BRK, 1, CI_NONE }, + { "bvc", OPC_BVC, 2, CI_BRA }, + { "bvs", OPC_BVS, 2, CI_BRA }, + { "clc", OPC_CLC, 1, CI_CHG_NONE }, + { "cld", OPC_CLD, 1, CI_CHG_NONE }, + { "cli", OPC_CLI, 1, CI_CHG_NONE }, + { "clv", OPC_CLV, 1, CI_CHG_NONE }, + { "cmp", OPC_CMP, 0, CI_USE_A }, + { "cpx", OPC_CPX, 0, CI_USE_X }, + { "cpy", OPC_CPY, 0, CI_USE_Y }, + { "dea", OPC_DEA, 1, CI_USE_A | CI_CHG_A }, + { "dec", OPC_DEC, 0, CI_NONE }, + { "dex", OPC_DEX, 1, CI_USE_X | CI_CHG_X }, + { "dey", OPC_DEY, 1, CI_USE_Y | CI_CHG_Y }, + { "eor", OPC_EOR, 0, CI_USE_A | CI_CHG_A }, + { "ina", OPC_INA, 1, CI_USE_A | CI_CHG_A }, + { "inc", OPC_INC, 0, CI_NONE }, + { "inx", OPC_INX, 1, CI_USE_X | CI_CHG_X }, + { "iny", OPC_INY, 1, CI_USE_Y | CI_CHG_Y }, + { "jcc", OPC_JCC, 5, CI_BRA }, + { "jcs", OPC_JCS, 5, CI_BRA }, + { "jeq", OPC_JEQ, 5, CI_BRA }, + { "jmi", OPC_JMI, 5, CI_BRA }, + { "jmp", OPC_JMP, 3, CI_BRA }, + { "jne", OPC_JNE, 5, CI_BRA }, + { "jpl", OPC_JPL, 5, CI_BRA }, + { "jsr", OPC_JSR, 3, CI_BRA }, + { "jvc", OPC_JVC, 5, CI_BRA }, + { "jvs", OPC_JVS, 5, CI_BRA }, + { "lda", OPC_LDA, 0, CI_CHG_A }, + { "ldx", OPC_LDX, 0, CI_CHG_X }, + { "ldy", OPC_LDY, 0, CI_CHG_Y }, + { "lsr", OPC_LSR, 0, CI_USE_A | CI_CHG_A }, + { "nop", OPC_NOP, 1, CI_NONE }, + { "ora", OPC_ORA, 0, CI_USE_A | CI_CHG_A }, + { "pha", OPC_PHA, 1, CI_USE_A }, + { "php", OPC_PHP, 1, CI_NONE }, + { "phx", OPC_PHX, 1, CI_USE_X }, + { "phy", OPC_PHY, 1, CI_USE_Y }, + { "pla", OPC_PLA, 1, CI_CHG_A }, + { "plp", OPC_PLP, 1, CI_NONE }, + { "plx", OPC_PLX, 1, CI_CHG_X }, + { "ply", OPC_PLY, 1, CI_CHG_Y }, + { "rol", OPC_ROL, 0, CI_USE_A | CI_CHG_A }, + { "ror", OPC_ROR, 0, CI_USE_A | CI_CHG_A }, + { "rti", OPC_RTI, 1, CI_NONE }, + { "rts", OPC_RTS, 1, CI_NONE }, + { "sbc", OPC_SBC, 0, CI_USE_A | CI_CHG_A }, + { "sec", OPC_SEC, 1, CI_NONE }, + { "sed", OPC_SED, 1, CI_NONE }, + { "sei", OPC_SEI, 1, CI_NONE }, + { "sta", OPC_STA, 0, CI_USE_A }, + { "stx", OPC_STX, 0, CI_USE_X }, + { "sty", OPC_STY, 0, CI_USE_Y }, + { "tax", OPC_TAX, 1, CI_USE_A | CI_CHG_X }, + { "tay", OPC_TAY, 1, CI_USE_A | CI_CHG_Y }, + { "trb", OPC_TRB, 0, CI_USE_A }, + { "tsb", OPC_TSB, 0, CI_USE_A }, + { "tsx", OPC_TSX, 1, CI_CHG_X }, + { "txa", OPC_TXA, 1, CI_USE_X | CI_CHG_A }, + { "txs", OPC_TXS, 1, CI_USE_X }, + { "tya", OPC_TYA, 1, CI_USE_Y | CI_CHG_A } }; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -168,9 +176,13 @@ const OPCDesc* FindOpcode (const char* M) unsigned GetInsnSize (opc_t OPC, am_t AM) /* Return the size of the given instruction */ { - /* On the 6502 (and 65C02), the instruction size is determined only by the - * addressing mode. - */ + /* Get the opcode desc and check the size given there */ + const OPCDesc* D = &OPCTable[OPC]; + if (D->Size != 0) { + return D->Size; + } + + /* Check the addressing mode. */ switch (AM) { case AM_IMP: return 1; case AM_ACC: return 1; @@ -183,7 +195,6 @@ unsigned GetInsnSize (opc_t OPC, am_t AM) case AM_ZPX_IND: return 2; case AM_ZP_INDY: return 2; case AM_ZP_IND: return 2; - case AM_BRA: return 2; default: FAIL ("Invalid addressing mode"); } } diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index 024354470..6e0ca2382 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -76,8 +76,16 @@ typedef enum { OPC_INC, OPC_INX, OPC_INY, + OPC_JCC, + OPC_JCS, + OPC_JEQ, + OPC_JMI, OPC_JMP, + OPC_JNE, + OPC_JPL, OPC_JSR, + OPC_JVC, + OPC_JVS, OPC_LDA, OPC_LDX, OPC_LDY, @@ -134,6 +142,7 @@ typedef enum { typedef struct { char Mnemo[4]; /* Mnemonic */ opc_t OPC; /* Opcode */ + unsigned Size; /* Size, 0 means "check addressing mode" */ unsigned Info; /* Usage flags */ } OPCDesc; @@ -155,7 +164,7 @@ unsigned GetInsnSize (opc_t OPC, am_t AM); const OPCDesc* GetOPCDesc (opc_t OPC); /* Get an opcode description */ - + /* End of opcodes.h */ -- 2.39.5