1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 19:29:37 +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_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),

View File

@ -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;
/* Search for the zp location in the list */
const ZPInfo* Info = bsearch (Name, ZPInfoTable, ZPInfoCount,
sizeof(ZPInfo), CompareZPInfo);
/* 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;
}
/* 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. */

View File

@ -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 */
/*****************************************************************************/

View File

@ -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;
}

View File

@ -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 */
};