From f28be6d6579fcbf9e9a358d0c45ed1bb2514d689 Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 23 Sep 2001 09:20:55 +0000 Subject: [PATCH] Collect more info on zp registers git-svn-id: svn://svn.cc65.org/cc65/trunk@965 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 62 +++++------- src/cc65/codeinfo.c | 240 ++++++++++++++++++++++++-------------------- src/cc65/codeinfo.h | 37 ++++--- src/cc65/codeseg.c | 10 +- src/cc65/codeseg.h | 2 +- 5 files changed, 184 insertions(+), 167 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index 25113fa98..6b487adba 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -163,12 +163,18 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) case AM65_ABSX: case AM65_ABSY: if (IsZPName (E->Arg, &Use) && Use != REG_NONE) { - if (E->OPC == OP65_INC || E->OPC == OP65_DEC) { + if (E->OPC == OP65_ASL || E->OPC == OP65_DEC || + E->OPC == OP65_INC || E->OPC == OP65_LSR || + E->OPC == OP65_ROL || E->OPC == OP65_ROR || + E->OPC == OP65_TRB || E->OPC == OP65_TSB) { + /* The zp loc is both, input and output */ E->Chg |= Use; E->Use |= Use; } else if ((E->Info & OF_STORE) != 0) { + /* Just output */ E->Chg |= Use; } else { + /* Input only */ E->Use |= Use; } } @@ -182,7 +188,7 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) E->Use |= Use; } break; - + default: /* Keep gcc silent */ break; @@ -718,39 +724,23 @@ static char* RegInfoDesc (unsigned U, char* Buf) /* Return a string containing register info */ { Buf[0] = '\0'; - if (U & REG_SREG) { - strcat (Buf, "E"); - } - if (U & REG_A) { - strcat (Buf, "A"); - } - if (U & REG_X) { - strcat (Buf, "X"); - } - if (U & REG_Y) { - strcat (Buf, "Y"); - } - if (U & REG_TMP1) { - strcat (Buf, "T1"); - } - if (U & REG_TMP2) { - strcat (Buf, "T2"); - } - if (U & REG_TMP3) { - strcat (Buf, "T3"); - } - if (U & REG_PTR1) { - strcat (Buf, "P1"); - } - if (U & REG_PTR2) { - strcat (Buf, "P2"); - } - if (U & REG_PTR3) { - strcat (Buf, "P3"); - } - if (U & REG_PTR4) { - strcat (Buf, "P4"); - } + + strcat (Buf, U & REG_SREG? "E" : "_"); + strcat (Buf, U & REG_A? "A" : "_"); + strcat (Buf, U & REG_X? "X" : "_"); + strcat (Buf, U & REG_Y? "Y" : "_"); + strcat (Buf, U & REG_SP? "S" : "_"); + strcat (Buf, U & REG_TMP1? "T1" : "__"); + strcat (Buf, U & REG_TMP2? "T2" : "__"); + strcat (Buf, U & REG_TMP3? "T3" : "__"); + strcat (Buf, U & REG_TMP4? "T4" : "__"); + strcat (Buf, U & REG_PTR1? "1" : "_"); + strcat (Buf, U & REG_PTR2? "2" : "_"); + strcat (Buf, U & REG_PTR3? "3" : "_"); + strcat (Buf, U & REG_PTR4? "4" : "_"); + strcat (Buf, U & REG_SAVE? "V" : "_"); + strcat (Buf, U & REG_BANK? "B" : "_"); + return Buf; } @@ -844,7 +834,7 @@ void CE_Output (const CodeEntry* E, FILE* F) char Use [128]; char Chg [128]; fprintf (F, - "%*s; USE: %-18s CHG: %-18s SIZE: %u\n", + "%*s; USE: %-19s CHG: %-19s SIZE: %u\n", 30-Chars, "", RegInfoDesc (E->Use, Use), RegInfoDesc (E->Chg, Chg), diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 43803840e..3eeb48506 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -66,91 +66,94 @@ struct FuncInfo { }; static const FuncInfo FuncInfoTable[] = { - { "addysp", REG_Y, REG_NONE }, - { "aslax1", REG_AX, REG_AX | REG_TMP1 }, - { "aslax2", REG_AX, REG_AX | REG_TMP1 }, - { "aslax3", REG_AX, REG_AX | REG_TMP1 }, - { "aslax4", REG_AX, REG_AX | REG_TMP1 }, - { "bnega", REG_A, REG_AX }, - { "bnegax", REG_AX, REG_AX }, - { "bnegeax", REG_EAX, REG_EAX }, - { "booleq", REG_NONE, REG_AX }, - { "boolge", REG_NONE, REG_AX }, - { "boolgt", REG_NONE, REG_AX }, - { "boolle", REG_NONE, REG_AX }, - { "boollt", REG_NONE, REG_AX }, - { "boolne", REG_NONE, REG_AX }, - { "booluge", REG_NONE, REG_AX }, - { "boolugt", REG_NONE, REG_AX }, - { "boolule", REG_NONE, REG_AX }, - { "boolult", REG_NONE, REG_AX }, - { "complax", REG_AX, REG_AX }, - { "decax1", REG_AX, REG_AX }, - { "decax2", REG_AX, REG_AX }, - { "decax3", REG_AX, REG_AX }, - { "decax4", REG_AX, REG_AX }, - { "decax5", REG_AX, REG_AX }, - { "decax6", REG_AX, REG_AX }, - { "decax7", REG_AX, REG_AX }, - { "decax8", REG_AX, REG_AX }, - { "decaxy", REG_AXY, REG_AX | REG_TMP1 }, - { "decsp1", REG_NONE, REG_Y }, - { "decsp2", REG_NONE, REG_A }, - { "decsp3", REG_NONE, REG_A }, - { "decsp4", REG_NONE, REG_A }, - { "decsp5", REG_NONE, REG_A }, - { "decsp6", REG_NONE, REG_A }, - { "decsp7", REG_NONE, REG_A }, - { "decsp8", REG_NONE, REG_A }, - { "incax1", REG_AX, REG_AX }, - { "incax2", REG_AX, REG_AX }, - { "incsp1", REG_NONE, REG_NONE }, - { "incsp2", REG_NONE, REG_Y }, - { "incsp3", REG_NONE, REG_Y }, - { "incsp4", REG_NONE, REG_Y }, - { "incsp5", REG_NONE, REG_Y }, - { "incsp6", REG_NONE, REG_Y }, - { "incsp7", REG_NONE, REG_Y }, - { "incsp8", REG_NONE, REG_Y }, - { "ldaidx", REG_AXY, REG_AX | REG_PTR1 }, - { "ldauidx", REG_AXY, REG_AX | REG_PTR1 }, - { "ldax0sp", REG_Y, REG_AX }, - { "ldaxi", REG_AX, REG_AXY | REG_PTR1 }, - { "ldaxidx", REG_AXY, REG_AX | REG_PTR1 }, - { "ldaxysp", REG_Y, REG_AX }, - { "leaasp", REG_A, REG_AX }, - { "negax", REG_AX, REG_AX }, - { "pusha", REG_A, REG_Y }, - { "pusha0", REG_A, REG_XY }, - { "pushax", REG_AX, REG_Y }, - { "pusheax", REG_EAX, REG_Y }, - { "pushw0sp", REG_NONE, REG_AXY }, - { "pushwysp", REG_Y, REG_AXY }, - { "shlax1", REG_AX, REG_AX | REG_TMP1 }, - { "shlax2", REG_AX, REG_AX | REG_TMP1 }, - { "shlax3", REG_AX, REG_AX | REG_TMP1 }, - { "shlax4", REG_AX, REG_AX | REG_TMP1 }, - { "shrax1", REG_AX, REG_AX | REG_TMP1 }, - { "shrax2", REG_AX, REG_AX | REG_TMP1 }, - { "shrax3", REG_AX, REG_AX | REG_TMP1 }, - { "shrax4", REG_AX, REG_AX | REG_TMP1 }, - { "shreax1", REG_EAX, REG_AX | REG_TMP1 }, - { "shreax2", REG_EAX, REG_AX | REG_TMP1 }, - { "shreax3", REG_EAX, REG_AX | REG_TMP1 }, - { "shreax4", REG_EAX, REG_AX | REG_TMP1 }, - { "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 }, - { "stax0sp", REG_AX, REG_Y }, - { "tosicmp", REG_AX, REG_AXY | REG_SREG }, - { "tosdiva0", REG_AX, REG_ALL }, - { "tosdivax", REG_AX, REG_ALL }, - { "tosdiveax", REG_EAX, REG_ALL }, - { "tosmula0", REG_AX, REG_ALL }, - { "tosmulax", REG_AX, REG_ALL }, - { "tosmuleax", REG_EAX, REG_ALL }, - { "tosshreax", REG_EAX, REG_EAXY | REG_PTR1 | REG_PTR2 }, - { "tosumula0", REG_AX, REG_ALL }, - { "tosumulax", REG_AX, REG_ALL }, - { "tosumuleax", REG_EAX, REG_ALL }, + { "addysp", REG_Y, REG_NONE }, + { "aslax1", REG_AX, REG_AX | REG_TMP1 }, + { "aslax2", REG_AX, REG_AX | REG_TMP1 }, + { "aslax3", REG_AX, REG_AX | REG_TMP1 }, + { "aslax4", REG_AX, REG_AX | REG_TMP1 }, + { "bnega", REG_A, REG_AX }, + { "bnegax", REG_AX, REG_AX }, + { "bnegeax", REG_EAX, REG_EAX }, + { "booleq", REG_NONE, REG_AX }, + { "boolge", REG_NONE, REG_AX }, + { "boolgt", REG_NONE, REG_AX }, + { "boolle", REG_NONE, REG_AX }, + { "boollt", REG_NONE, REG_AX }, + { "boolne", REG_NONE, REG_AX }, + { "booluge", REG_NONE, REG_AX }, + { "boolugt", REG_NONE, REG_AX }, + { "boolule", REG_NONE, REG_AX }, + { "boolult", REG_NONE, REG_AX }, + { "complax", REG_AX, REG_AX }, + { "decax1", REG_AX, REG_AX }, + { "decax2", REG_AX, REG_AX }, + { "decax3", REG_AX, REG_AX }, + { "decax4", REG_AX, REG_AX }, + { "decax5", REG_AX, REG_AX }, + { "decax6", REG_AX, REG_AX }, + { "decax7", REG_AX, REG_AX }, + { "decax8", REG_AX, REG_AX }, + { "decaxy", REG_AXY, REG_AX | REG_TMP1 }, + { "decsp1", REG_NONE, REG_Y }, + { "decsp2", REG_NONE, REG_A }, + { "decsp3", REG_NONE, REG_A }, + { "decsp4", REG_NONE, REG_A }, + { "decsp5", REG_NONE, REG_A }, + { "decsp6", REG_NONE, REG_A }, + { "decsp7", REG_NONE, REG_A }, + { "decsp8", REG_NONE, REG_A }, + { "incax1", REG_AX, REG_AX }, + { "incax2", REG_AX, REG_AX }, + { "incsp1", REG_NONE, REG_NONE }, + { "incsp2", REG_NONE, REG_Y }, + { "incsp3", REG_NONE, REG_Y }, + { "incsp4", REG_NONE, REG_Y }, + { "incsp5", REG_NONE, REG_Y }, + { "incsp6", REG_NONE, REG_Y }, + { "incsp7", REG_NONE, REG_Y }, + { "incsp8", REG_NONE, REG_Y }, + { "laddeq", REG_EAXY | REG_PTR1, REG_EAXY }, + { "laddeq1", REG_Y | REG_PTR1, REG_EAXY }, + { "laddeqa", REG_AY | REG_PTR1, REG_EAXY }, + { "ldaidx", REG_AXY, REG_AX | REG_PTR1 }, + { "ldauidx", REG_AXY, REG_AX | REG_PTR1 }, + { "ldax0sp", REG_Y, REG_AX }, + { "ldaxi", REG_AX, REG_AXY | REG_PTR1 }, + { "ldaxidx", REG_AXY, REG_AX | REG_PTR1 }, + { "ldaxysp", REG_Y, REG_AX }, + { "leaasp", REG_A, REG_AX }, + { "negax", REG_AX, REG_AX }, + { "pusha", REG_A, REG_Y }, + { "pusha0", REG_A, REG_XY }, + { "pushax", REG_AX, REG_Y }, + { "pusheax", REG_EAX, REG_Y }, + { "pushw0sp", REG_NONE, REG_AXY }, + { "pushwysp", REG_Y, REG_AXY }, + { "shlax1", REG_AX, REG_AX | REG_TMP1 }, + { "shlax2", REG_AX, REG_AX | REG_TMP1 }, + { "shlax3", REG_AX, REG_AX | REG_TMP1 }, + { "shlax4", REG_AX, REG_AX | REG_TMP1 }, + { "shrax1", REG_AX, REG_AX | REG_TMP1 }, + { "shrax2", REG_AX, REG_AX | REG_TMP1 }, + { "shrax3", REG_AX, REG_AX | REG_TMP1 }, + { "shrax4", REG_AX, REG_AX | REG_TMP1 }, + { "shreax1", REG_EAX, REG_AX | REG_TMP1 }, + { "shreax2", REG_EAX, REG_AX | REG_TMP1 }, + { "shreax3", REG_EAX, REG_AX | REG_TMP1 }, + { "shreax4", REG_EAX, REG_AX | REG_TMP1 }, + { "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 }, + { "stax0sp", REG_AX, REG_Y }, + { "tosicmp", REG_AX, REG_AXY | REG_SREG }, + { "tosdiva0", REG_AX, REG_ALL }, + { "tosdivax", REG_AX, REG_ALL }, + { "tosdiveax", REG_EAX, REG_ALL }, + { "tosmula0", REG_AX, REG_ALL }, + { "tosmulax", REG_AX, REG_ALL }, + { "tosmuleax", REG_EAX, REG_ALL }, + { "tosshreax", REG_EAX, REG_EAXY | REG_PTR1 | REG_PTR2 }, + { "tosumula0", REG_AX, REG_ALL }, + { "tosumulax", REG_AX, REG_ALL }, + { "tosumuleax", REG_EAX, REG_ALL }, }; #define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0])) @@ -166,13 +169,14 @@ static const ZPInfo ZPInfoTable[] = { { 4, "ptr2", REG_PTR2 }, { 4, "ptr3", REG_PTR3 }, { 4, "ptr4", REG_PTR4 }, - { 7, "regbank", REG_NONE }, - { 7, "regsave", REG_NONE }, - { 2, "sp", REG_NONE }, + { 7, "regbank", REG_BANK }, + { 7, "regsave", REG_SAVE }, + { 2, "sp", REG_SP }, { 4, "sreg", REG_SREG }, { 4, "tmp1", REG_TMP1 }, { 4, "tmp2", REG_TMP2 }, { 4, "tmp3", REG_TMP3 }, + { 4, "tmp4", REG_TMP4 }, }; #define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0])) @@ -263,39 +267,57 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) +static int CompareZPInfo (const void* Name, const void* Info) +/* Compare function for bsearch */ +{ + /* Cast the pointers to the correct data type */ + const char* N = (const char*) Name; + const ZPInfo* E = (const ZPInfo*) Info; + + /* Do the compare. Be careful because of the length (Info may contain + * more than just the zeropage name). + */ + int Res = strncmp (N, E->Name, E->Len); + if (Res == 0 && (N[E->Len] != '\0' && N[E->Len] != '+')) { + /* Name is actually longer than Info->Name */ + Res = -1; + } + return Res; +} + + + int IsZPName (const char* Name, unsigned short* RegInfo) /* Return true if the given name is a zero page symbol. If the RegInfo * pointer is not NULL, it is filled with the register info for the * zero page location found. */ { - unsigned I; - const ZPInfo* Info; - - /* Because of the low number of symbols, we do a linear search here */ - for (I = 0, Info = ZPInfoTable; I < ZPInfoCount; ++I, ++Info) { - if (strncmp (Name, Info->Name, Info->Len) == 0 && - (Name[Info->Len] == '\0' || Name[Info->Len] == '+')) { - /* Found */ - if (RegInfo) { - *RegInfo = Info->RegInfo; - } - return 1; - } + /* Search for the zp location in the list */ + const ZPInfo* Info = bsearch (Name, ZPInfoTable, ZPInfoCount, + sizeof(ZPInfo), CompareZPInfo); + + /* Did we find it? */ + if (Info) { + /* Found, store register info if requested. */ + if (RegInfo) { + *RegInfo = Info->RegInfo; + } + return 1; + } else { + /* Not found */ + return 0; } - - /* Not found */ - return 0; } static unsigned GetRegInfo1 (CodeSeg* S, - CodeEntry* E, - int Index, - Collection* Visited, - unsigned Used, - unsigned Unused); + CodeEntry* E, + int Index, + Collection* Visited, + unsigned Used, + unsigned Unused); /* Recursively called subfunction for GetRegInfo. */ diff --git a/src/cc65/codeinfo.h b/src/cc65/codeinfo.h index 526fb5317..ff4c866e4 100644 --- a/src/cc65/codeinfo.h +++ b/src/cc65/codeinfo.h @@ -59,32 +59,31 @@ struct CodeSeg; #define REG_A 0x0001U #define REG_X 0x0002U #define REG_Y 0x0004U -#define REG_SREG_LO 0x0008U -#define REG_SREG_HI 0x0010U -#define REG_TMP1 0x0020U -#define REG_TMP2 0x0040U -#define REG_TMP3 0x0080U -#define REG_PTR1_LO 0x0100U -#define REG_PTR1_HI 0x0200U -#define REG_PTR2_LO 0x0400U -#define REG_PTR2_HI 0x0800U -#define REG_PTR3_LO 0x1000U -#define REG_PTR3_HI 0x2000U -#define REG_PTR4_LO 0x4000U -#define REG_PTR4_HI 0x8000U +#define REG_TMP1 0x0010U +#define REG_TMP2 0x0020U +#define REG_TMP3 0x0040U +#define REG_TMP4 0x0080U +#define REG_PTR1 0x0100U +#define REG_PTR2 0x0200U +#define REG_PTR3 0x0400U +#define REG_PTR4 0x0800U +#define REG_SREG 0x1000U +#define REG_SP 0x2000U +#define REG_SAVE 0x4000U +#define REG_BANK 0x8000U + +/* Combined register defines */ #define REG_AX (REG_A | REG_X) -#define REG_SREG (REG_SREG_LO | REG_SREG_HI) -#define REG_EAX (REG_AX | REG_SREG) +#define REG_AY (REG_A | REG_Y) #define REG_XY (REG_X | REG_Y) #define REG_AXY (REG_AX | REG_Y) +#define REG_EAX (REG_AX | REG_SREG) #define REG_EAXY (REG_EAX | REG_Y) -#define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI) -#define REG_PTR2 (REG_PTR2_LO | REG_PTR2_HI) -#define REG_PTR3 (REG_PTR3_LO | REG_PTR3_HI) -#define REG_PTR4 (REG_PTR4_LO | REG_PTR4_HI) +#define REG_ZP 0xFFF0U #define REG_ALL 0xFFFFU + /*****************************************************************************/ /* Code */ /*****************************************************************************/ diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index 04fab6165..cc4ee7364 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -397,6 +397,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func) /* Create a new code segment, initialize and return it */ { unsigned I; + const type* RetType; /* Allocate memory */ CodeSeg* S = xmalloc (sizeof (CodeSeg)); @@ -413,8 +414,13 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func) /* If we have a function given, get the return type of the function. * Assume ANY return type besides void will use the A and X registers. */ - if (S->Func && !IsTypeVoid (GetFuncReturn (Func->Type))) { - S->ExitRegs = REG_AX; + RetType = GetFuncReturn (Func->Type); + if (S->Func && !IsTypeVoid (RetType)) { + if (SizeOf (RetType) == SizeOf (type_long)) { + S->ExitRegs = REG_EAX; + } else { + S->ExitRegs = REG_AX; + } } else { S->ExitRegs = REG_NONE; } diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h index 1218634a2..40ceb77a1 100644 --- a/src/cc65/codeseg.h +++ b/src/cc65/codeseg.h @@ -80,7 +80,7 @@ struct CodeSeg { Collection Entries; /* List of code entries */ Collection Labels; /* Labels for next insn */ CodeLabel* LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */ - unsigned char ExitRegs; /* Register use on exit */ + unsigned short ExitRegs; /* Register use on exit */ }; -- 2.39.5