1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-11 11:30:13 +00:00

Collect more info on zp registers

git-svn-id: svn://svn.cc65.org/cc65/trunk@965 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-09-23 09:20:55 +00:00
parent a6aa5512d5
commit f28be6d657
5 changed files with 183 additions and 166 deletions

View File

@ -163,12 +163,18 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
case AM65_ABSX: case AM65_ABSX:
case AM65_ABSY: case AM65_ABSY:
if (IsZPName (E->Arg, &Use) && Use != REG_NONE) { 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->Chg |= Use;
E->Use |= Use; E->Use |= Use;
} else if ((E->Info & OF_STORE) != 0) { } else if ((E->Info & OF_STORE) != 0) {
/* Just output */
E->Chg |= Use; E->Chg |= Use;
} else { } else {
/* Input only */
E->Use |= Use; E->Use |= Use;
} }
} }
@ -182,7 +188,7 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
E->Use |= Use; E->Use |= Use;
} }
break; break;
default: default:
/* Keep gcc silent */ /* Keep gcc silent */
break; break;
@ -718,39 +724,23 @@ static char* RegInfoDesc (unsigned U, char* Buf)
/* Return a string containing register info */ /* Return a string containing register info */
{ {
Buf[0] = '\0'; Buf[0] = '\0';
if (U & REG_SREG) {
strcat (Buf, "E"); strcat (Buf, U & REG_SREG? "E" : "_");
} strcat (Buf, U & REG_A? "A" : "_");
if (U & REG_A) { strcat (Buf, U & REG_X? "X" : "_");
strcat (Buf, "A"); strcat (Buf, U & REG_Y? "Y" : "_");
} strcat (Buf, U & REG_SP? "S" : "_");
if (U & REG_X) { strcat (Buf, U & REG_TMP1? "T1" : "__");
strcat (Buf, "X"); strcat (Buf, U & REG_TMP2? "T2" : "__");
} strcat (Buf, U & REG_TMP3? "T3" : "__");
if (U & REG_Y) { strcat (Buf, U & REG_TMP4? "T4" : "__");
strcat (Buf, "Y"); strcat (Buf, U & REG_PTR1? "1" : "_");
} strcat (Buf, U & REG_PTR2? "2" : "_");
if (U & REG_TMP1) { strcat (Buf, U & REG_PTR3? "3" : "_");
strcat (Buf, "T1"); strcat (Buf, U & REG_PTR4? "4" : "_");
} strcat (Buf, U & REG_SAVE? "V" : "_");
if (U & REG_TMP2) { strcat (Buf, U & REG_BANK? "B" : "_");
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");
}
return Buf; return Buf;
} }
@ -844,7 +834,7 @@ void CE_Output (const CodeEntry* E, FILE* F)
char Use [128]; char Use [128];
char Chg [128]; char Chg [128];
fprintf (F, fprintf (F,
"%*s; USE: %-18s CHG: %-18s SIZE: %u\n", "%*s; USE: %-19s CHG: %-19s SIZE: %u\n",
30-Chars, "", 30-Chars, "",
RegInfoDesc (E->Use, Use), RegInfoDesc (E->Use, Use),
RegInfoDesc (E->Chg, Chg), RegInfoDesc (E->Chg, Chg),

View File

@ -66,91 +66,94 @@ struct FuncInfo {
}; };
static const FuncInfo FuncInfoTable[] = { static const FuncInfo FuncInfoTable[] = {
{ "addysp", REG_Y, REG_NONE }, { "addysp", REG_Y, REG_NONE },
{ "aslax1", REG_AX, REG_AX | REG_TMP1 }, { "aslax1", REG_AX, REG_AX | REG_TMP1 },
{ "aslax2", REG_AX, REG_AX | REG_TMP1 }, { "aslax2", REG_AX, REG_AX | REG_TMP1 },
{ "aslax3", REG_AX, REG_AX | REG_TMP1 }, { "aslax3", REG_AX, REG_AX | REG_TMP1 },
{ "aslax4", REG_AX, REG_AX | REG_TMP1 }, { "aslax4", REG_AX, REG_AX | REG_TMP1 },
{ "bnega", REG_A, REG_AX }, { "bnega", REG_A, REG_AX },
{ "bnegax", REG_AX, REG_AX }, { "bnegax", REG_AX, REG_AX },
{ "bnegeax", REG_EAX, REG_EAX }, { "bnegeax", REG_EAX, REG_EAX },
{ "booleq", REG_NONE, REG_AX }, { "booleq", REG_NONE, REG_AX },
{ "boolge", REG_NONE, REG_AX }, { "boolge", REG_NONE, REG_AX },
{ "boolgt", REG_NONE, REG_AX }, { "boolgt", REG_NONE, REG_AX },
{ "boolle", REG_NONE, REG_AX }, { "boolle", REG_NONE, REG_AX },
{ "boollt", REG_NONE, REG_AX }, { "boollt", REG_NONE, REG_AX },
{ "boolne", REG_NONE, REG_AX }, { "boolne", REG_NONE, REG_AX },
{ "booluge", REG_NONE, REG_AX }, { "booluge", REG_NONE, REG_AX },
{ "boolugt", REG_NONE, REG_AX }, { "boolugt", REG_NONE, REG_AX },
{ "boolule", REG_NONE, REG_AX }, { "boolule", REG_NONE, REG_AX },
{ "boolult", REG_NONE, REG_AX }, { "boolult", REG_NONE, REG_AX },
{ "complax", REG_AX, REG_AX }, { "complax", REG_AX, REG_AX },
{ "decax1", REG_AX, REG_AX }, { "decax1", REG_AX, REG_AX },
{ "decax2", REG_AX, REG_AX }, { "decax2", REG_AX, REG_AX },
{ "decax3", REG_AX, REG_AX }, { "decax3", REG_AX, REG_AX },
{ "decax4", REG_AX, REG_AX }, { "decax4", REG_AX, REG_AX },
{ "decax5", REG_AX, REG_AX }, { "decax5", REG_AX, REG_AX },
{ "decax6", REG_AX, REG_AX }, { "decax6", REG_AX, REG_AX },
{ "decax7", REG_AX, REG_AX }, { "decax7", REG_AX, REG_AX },
{ "decax8", REG_AX, REG_AX }, { "decax8", REG_AX, REG_AX },
{ "decaxy", REG_AXY, REG_AX | REG_TMP1 }, { "decaxy", REG_AXY, REG_AX | REG_TMP1 },
{ "decsp1", REG_NONE, REG_Y }, { "decsp1", REG_NONE, REG_Y },
{ "decsp2", REG_NONE, REG_A }, { "decsp2", REG_NONE, REG_A },
{ "decsp3", REG_NONE, REG_A }, { "decsp3", REG_NONE, REG_A },
{ "decsp4", REG_NONE, REG_A }, { "decsp4", REG_NONE, REG_A },
{ "decsp5", REG_NONE, REG_A }, { "decsp5", REG_NONE, REG_A },
{ "decsp6", REG_NONE, REG_A }, { "decsp6", REG_NONE, REG_A },
{ "decsp7", REG_NONE, REG_A }, { "decsp7", REG_NONE, REG_A },
{ "decsp8", REG_NONE, REG_A }, { "decsp8", REG_NONE, REG_A },
{ "incax1", REG_AX, REG_AX }, { "incax1", REG_AX, REG_AX },
{ "incax2", REG_AX, REG_AX }, { "incax2", REG_AX, REG_AX },
{ "incsp1", REG_NONE, REG_NONE }, { "incsp1", REG_NONE, REG_NONE },
{ "incsp2", REG_NONE, REG_Y }, { "incsp2", REG_NONE, REG_Y },
{ "incsp3", REG_NONE, REG_Y }, { "incsp3", REG_NONE, REG_Y },
{ "incsp4", REG_NONE, REG_Y }, { "incsp4", REG_NONE, REG_Y },
{ "incsp5", REG_NONE, REG_Y }, { "incsp5", REG_NONE, REG_Y },
{ "incsp6", REG_NONE, REG_Y }, { "incsp6", REG_NONE, REG_Y },
{ "incsp7", REG_NONE, REG_Y }, { "incsp7", REG_NONE, REG_Y },
{ "incsp8", REG_NONE, REG_Y }, { "incsp8", REG_NONE, REG_Y },
{ "ldaidx", REG_AXY, REG_AX | REG_PTR1 }, { "laddeq", REG_EAXY | REG_PTR1, REG_EAXY },
{ "ldauidx", REG_AXY, REG_AX | REG_PTR1 }, { "laddeq1", REG_Y | REG_PTR1, REG_EAXY },
{ "ldax0sp", REG_Y, REG_AX }, { "laddeqa", REG_AY | REG_PTR1, REG_EAXY },
{ "ldaxi", REG_AX, REG_AXY | REG_PTR1 }, { "ldaidx", REG_AXY, REG_AX | REG_PTR1 },
{ "ldaxidx", REG_AXY, REG_AX | REG_PTR1 }, { "ldauidx", REG_AXY, REG_AX | REG_PTR1 },
{ "ldaxysp", REG_Y, REG_AX }, { "ldax0sp", REG_Y, REG_AX },
{ "leaasp", REG_A, REG_AX }, { "ldaxi", REG_AX, REG_AXY | REG_PTR1 },
{ "negax", REG_AX, REG_AX }, { "ldaxidx", REG_AXY, REG_AX | REG_PTR1 },
{ "pusha", REG_A, REG_Y }, { "ldaxysp", REG_Y, REG_AX },
{ "pusha0", REG_A, REG_XY }, { "leaasp", REG_A, REG_AX },
{ "pushax", REG_AX, REG_Y }, { "negax", REG_AX, REG_AX },
{ "pusheax", REG_EAX, REG_Y }, { "pusha", REG_A, REG_Y },
{ "pushw0sp", REG_NONE, REG_AXY }, { "pusha0", REG_A, REG_XY },
{ "pushwysp", REG_Y, REG_AXY }, { "pushax", REG_AX, REG_Y },
{ "shlax1", REG_AX, REG_AX | REG_TMP1 }, { "pusheax", REG_EAX, REG_Y },
{ "shlax2", REG_AX, REG_AX | REG_TMP1 }, { "pushw0sp", REG_NONE, REG_AXY },
{ "shlax3", REG_AX, REG_AX | REG_TMP1 }, { "pushwysp", REG_Y, REG_AXY },
{ "shlax4", REG_AX, REG_AX | REG_TMP1 }, { "shlax1", REG_AX, REG_AX | REG_TMP1 },
{ "shrax1", REG_AX, REG_AX | REG_TMP1 }, { "shlax2", REG_AX, REG_AX | REG_TMP1 },
{ "shrax2", REG_AX, REG_AX | REG_TMP1 }, { "shlax3", REG_AX, REG_AX | REG_TMP1 },
{ "shrax3", REG_AX, REG_AX | REG_TMP1 }, { "shlax4", REG_AX, REG_AX | REG_TMP1 },
{ "shrax4", REG_AX, REG_AX | REG_TMP1 }, { "shrax1", REG_AX, REG_AX | REG_TMP1 },
{ "shreax1", REG_EAX, REG_AX | REG_TMP1 }, { "shrax2", REG_AX, REG_AX | REG_TMP1 },
{ "shreax2", REG_EAX, REG_AX | REG_TMP1 }, { "shrax3", REG_AX, REG_AX | REG_TMP1 },
{ "shreax3", REG_EAX, REG_AX | REG_TMP1 }, { "shrax4", REG_AX, REG_AX | REG_TMP1 },
{ "shreax4", REG_EAX, REG_AX | REG_TMP1 }, { "shreax1", REG_EAX, REG_AX | REG_TMP1 },
{ "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 }, { "shreax2", REG_EAX, REG_AX | REG_TMP1 },
{ "stax0sp", REG_AX, REG_Y }, { "shreax3", REG_EAX, REG_AX | REG_TMP1 },
{ "tosicmp", REG_AX, REG_AXY | REG_SREG }, { "shreax4", REG_EAX, REG_AX | REG_TMP1 },
{ "tosdiva0", REG_AX, REG_ALL }, { "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 },
{ "tosdivax", REG_AX, REG_ALL }, { "stax0sp", REG_AX, REG_Y },
{ "tosdiveax", REG_EAX, REG_ALL }, { "tosicmp", REG_AX, REG_AXY | REG_SREG },
{ "tosmula0", REG_AX, REG_ALL }, { "tosdiva0", REG_AX, REG_ALL },
{ "tosmulax", REG_AX, REG_ALL }, { "tosdivax", REG_AX, REG_ALL },
{ "tosmuleax", REG_EAX, REG_ALL }, { "tosdiveax", REG_EAX, REG_ALL },
{ "tosshreax", REG_EAX, REG_EAXY | REG_PTR1 | REG_PTR2 }, { "tosmula0", REG_AX, REG_ALL },
{ "tosumula0", REG_AX, REG_ALL }, { "tosmulax", REG_AX, REG_ALL },
{ "tosumulax", REG_AX, REG_ALL }, { "tosmuleax", REG_EAX, REG_ALL },
{ "tosumuleax", 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])) #define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
@ -166,13 +169,14 @@ static const ZPInfo ZPInfoTable[] = {
{ 4, "ptr2", REG_PTR2 }, { 4, "ptr2", REG_PTR2 },
{ 4, "ptr3", REG_PTR3 }, { 4, "ptr3", REG_PTR3 },
{ 4, "ptr4", REG_PTR4 }, { 4, "ptr4", REG_PTR4 },
{ 7, "regbank", REG_NONE }, { 7, "regbank", REG_BANK },
{ 7, "regsave", REG_NONE }, { 7, "regsave", REG_SAVE },
{ 2, "sp", REG_NONE }, { 2, "sp", REG_SP },
{ 4, "sreg", REG_SREG }, { 4, "sreg", REG_SREG },
{ 4, "tmp1", REG_TMP1 }, { 4, "tmp1", REG_TMP1 },
{ 4, "tmp2", REG_TMP2 }, { 4, "tmp2", REG_TMP2 },
{ 4, "tmp3", REG_TMP3 }, { 4, "tmp3", REG_TMP3 },
{ 4, "tmp4", REG_TMP4 },
}; };
#define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0])) #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) int IsZPName (const char* Name, unsigned short* RegInfo)
/* Return true if the given name is a zero page symbol. If the 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 * pointer is not NULL, it is filled with the register info for the
* zero page location found. * zero page location found.
*/ */
{ {
unsigned I; /* Search for the zp location in the list */
const ZPInfo* Info; const ZPInfo* Info = bsearch (Name, ZPInfoTable, ZPInfoCount,
sizeof(ZPInfo), CompareZPInfo);
/* Because of the low number of symbols, we do a linear search here */ /* Did we find it? */
for (I = 0, Info = ZPInfoTable; I < ZPInfoCount; ++I, ++Info) { if (Info) {
if (strncmp (Name, Info->Name, Info->Len) == 0 && /* Found, store register info if requested. */
(Name[Info->Len] == '\0' || Name[Info->Len] == '+')) { if (RegInfo) {
/* Found */ *RegInfo = Info->RegInfo;
if (RegInfo) { }
*RegInfo = Info->RegInfo; return 1;
} } else {
return 1; /* Not found */
} return 0;
} }
/* Not found */
return 0;
} }
static unsigned GetRegInfo1 (CodeSeg* S, static unsigned GetRegInfo1 (CodeSeg* S,
CodeEntry* E, CodeEntry* E,
int Index, int Index,
Collection* Visited, Collection* Visited,
unsigned Used, unsigned Used,
unsigned Unused); unsigned Unused);
/* Recursively called subfunction for GetRegInfo. */ /* Recursively called subfunction for GetRegInfo. */

View File

@ -59,32 +59,31 @@ struct CodeSeg;
#define REG_A 0x0001U #define REG_A 0x0001U
#define REG_X 0x0002U #define REG_X 0x0002U
#define REG_Y 0x0004U #define REG_Y 0x0004U
#define REG_SREG_LO 0x0008U #define REG_TMP1 0x0010U
#define REG_SREG_HI 0x0010U #define REG_TMP2 0x0020U
#define REG_TMP1 0x0020U #define REG_TMP3 0x0040U
#define REG_TMP2 0x0040U #define REG_TMP4 0x0080U
#define REG_TMP3 0x0080U #define REG_PTR1 0x0100U
#define REG_PTR1_LO 0x0100U #define REG_PTR2 0x0200U
#define REG_PTR1_HI 0x0200U #define REG_PTR3 0x0400U
#define REG_PTR2_LO 0x0400U #define REG_PTR4 0x0800U
#define REG_PTR2_HI 0x0800U #define REG_SREG 0x1000U
#define REG_PTR3_LO 0x1000U #define REG_SP 0x2000U
#define REG_PTR3_HI 0x2000U #define REG_SAVE 0x4000U
#define REG_PTR4_LO 0x4000U #define REG_BANK 0x8000U
#define REG_PTR4_HI 0x8000U
/* Combined register defines */
#define REG_AX (REG_A | REG_X) #define REG_AX (REG_A | REG_X)
#define REG_SREG (REG_SREG_LO | REG_SREG_HI) #define REG_AY (REG_A | REG_Y)
#define REG_EAX (REG_AX | REG_SREG)
#define REG_XY (REG_X | REG_Y) #define REG_XY (REG_X | REG_Y)
#define REG_AXY (REG_AX | 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_EAXY (REG_EAX | REG_Y)
#define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI) #define REG_ZP 0xFFF0U
#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_ALL 0xFFFFU #define REG_ALL 0xFFFFU
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/

View File

@ -397,6 +397,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
/* Create a new code segment, initialize and return it */ /* Create a new code segment, initialize and return it */
{ {
unsigned I; unsigned I;
const type* RetType;
/* Allocate memory */ /* Allocate memory */
CodeSeg* S = xmalloc (sizeof (CodeSeg)); 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. /* 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. * Assume ANY return type besides void will use the A and X registers.
*/ */
if (S->Func && !IsTypeVoid (GetFuncReturn (Func->Type))) { RetType = GetFuncReturn (Func->Type);
S->ExitRegs = REG_AX; if (S->Func && !IsTypeVoid (RetType)) {
if (SizeOf (RetType) == SizeOf (type_long)) {
S->ExitRegs = REG_EAX;
} else {
S->ExitRegs = REG_AX;
}
} else { } else {
S->ExitRegs = REG_NONE; S->ExitRegs = REG_NONE;
} }

View File

@ -80,7 +80,7 @@ struct CodeSeg {
Collection Entries; /* List of code entries */ Collection Entries; /* List of code entries */
Collection Labels; /* Labels for next insn */ Collection Labels; /* Labels for next insn */
CodeLabel* LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */ CodeLabel* LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */
unsigned char ExitRegs; /* Register use on exit */ unsigned short ExitRegs; /* Register use on exit */
}; };