Stack adjustment code optimizations.
This commit is contained in:
parent
249248ccc8
commit
d3665b263e
5 changed files with 116 additions and 5 deletions
|
@ -69,7 +69,7 @@
|
|||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "output.h"
|
||||
|
||||
#include "symtab.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -613,7 +613,86 @@ static unsigned OptStackPtrOps (CodeSeg* S)
|
|||
return Changes;
|
||||
}
|
||||
|
||||
static unsigned OptGotoSPAdj (CodeSeg* S)
|
||||
/* Remove unnecessary SP adjustment while gotoing
|
||||
*/
|
||||
{
|
||||
unsigned Changes = 0;
|
||||
unsigned I;
|
||||
|
||||
/* Walk over the entries */
|
||||
I = 0;
|
||||
while (I < CS_GetEntryCount (S)) {
|
||||
|
||||
CodeEntry* L[10], *X;
|
||||
unsigned short adjustment;
|
||||
const char* Arg;
|
||||
|
||||
/* Get next entry */
|
||||
L[0] = CS_GetEntry (S, I);
|
||||
|
||||
/* Check for the sequence */
|
||||
if (L[0]->OPC == OP65_PHA &&
|
||||
CS_GetEntries (S, L+1, I+1, 9) &&
|
||||
L[1]->OPC == OP65_LDA &&
|
||||
L[1]->AM == AM65_ABS &&
|
||||
L[2]->OPC == OP65_CLC &&
|
||||
L[3]->OPC == OP65_ADC &&
|
||||
strcmp (L[3]->Arg, "sp") == 0 &&
|
||||
L[6]->OPC == OP65_ADC &&
|
||||
strcmp (L[6]->Arg, "sp+1") == 0 &&
|
||||
L[9]->OPC == OP65_JMP
|
||||
) {
|
||||
printf("Goto SP adjustment found. Jump to: %s, data Label: %s\n", L[9]->Arg, L[1]->Arg);
|
||||
adjustment = FindSPAdjustment(L[1]->Arg);
|
||||
|
||||
if (adjustment == 0) {
|
||||
CS_DelEntries (S, I, 9);
|
||||
}
|
||||
else if (adjustment > 255) {
|
||||
Arg = MakeHexArg (adjustment & 0xff);
|
||||
X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[1]->LI);
|
||||
CS_InsertEntry(S, X, I + 1);
|
||||
Arg = MakeHexArg (adjustment >> 8);
|
||||
X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[5]->LI);
|
||||
CS_InsertEntry(S, X, I + 6);
|
||||
|
||||
CS_DelEntry(S, I + 2);
|
||||
CS_DelEntry(S, I + 6);
|
||||
}
|
||||
else if (adjustment > 8) {
|
||||
Arg = MakeHexArg (adjustment & 0xff);
|
||||
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
|
||||
CS_InsertEntry (S, X, I);
|
||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, "addysp", 0, L[1]->LI);
|
||||
CS_InsertEntry (S, X, I + 1);
|
||||
|
||||
CS_DelEntries(S, I + 2, 9);
|
||||
}
|
||||
else {
|
||||
char Buf[20];
|
||||
xsprintf (Buf, sizeof (Buf), "incsp%u", adjustment);
|
||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI);
|
||||
CS_InsertEntry (S, X, I);
|
||||
|
||||
CS_DelEntries(S, I + 1, 9);
|
||||
}
|
||||
/* Regenerate register info */
|
||||
CS_GenRegInfo (S);
|
||||
|
||||
/* Remember we had changes */
|
||||
Changes++;
|
||||
} else {
|
||||
|
||||
/* Next entry */
|
||||
++I;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Return the number of changes made */
|
||||
return Changes;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* struct OptFunc */
|
||||
|
@ -675,6 +754,7 @@ static OptFunc DOptDeadCode = { OptDeadCode, "OptDeadCode", 100, 0,
|
|||
static OptFunc DOptDeadJumps = { OptDeadJumps, "OptDeadJumps", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptDecouple = { OptDecouple, "OptDecouple", 100, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptDupLoads = { OptDupLoads, "OptDupLoads", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptGotoSPAdj = { OptGotoSPAdj, "OptGotoSPAdj", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptIndLoads1 = { OptIndLoads1, "OptIndLoads1", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptIndLoads2 = { OptIndLoads2, "OptIndLoads2", 0, 0, 0, 0, 0, 0 };
|
||||
static OptFunc DOptJumpCascades = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 };
|
||||
|
@ -774,6 +854,7 @@ static OptFunc* OptFuncs[] = {
|
|||
&DOptDeadJumps,
|
||||
&DOptDecouple,
|
||||
&DOptDupLoads,
|
||||
&DOptGotoSPAdj,
|
||||
&DOptIndLoads1,
|
||||
&DOptIndLoads2,
|
||||
&DOptJumpCascades,
|
||||
|
@ -1122,6 +1203,7 @@ static unsigned RunOptGroup1 (CodeSeg* S)
|
|||
{
|
||||
unsigned Changes = 0;
|
||||
|
||||
Changes += RunOptFunc (S, &DOptGotoSPAdj, 1);
|
||||
Changes += RunOptFunc (S, &DOptStackPtrOps, 5);
|
||||
Changes += RunOptFunc (S, &DOptPtrStore1, 1);
|
||||
Changes += RunOptFunc (S, &DOptPtrStore2, 1);
|
||||
|
@ -1229,6 +1311,7 @@ static unsigned RunOptGroup3 (CodeSeg* S)
|
|||
C += RunOptFunc (S, &DOptCmp6, 1);
|
||||
C += RunOptFunc (S, &DOptCmp7, 1);
|
||||
C += RunOptFunc (S, &DOptCmp9, 1);
|
||||
|
||||
C += RunOptFunc (S, &DOptTest1, 1);
|
||||
C += RunOptFunc (S, &DOptLoad1, 1);
|
||||
C += RunOptFunc (S, &DOptJumpTarget3, 1); /* After OptCondBranches2 */
|
||||
|
|
|
@ -134,7 +134,7 @@ typedef enum {
|
|||
typedef enum {
|
||||
AM65_IMP, /* implicit */
|
||||
AM65_ACC, /* accumulator */
|
||||
AM65_IMM, /* immidiate */
|
||||
AM65_IMM, /* immediate */
|
||||
AM65_ZP, /* zeropage */
|
||||
AM65_ZPX, /* zeropage,X */
|
||||
AM65_ZPY, /* zeropage,Y */
|
||||
|
|
|
@ -99,6 +99,7 @@ struct LiteralPool;
|
|||
#define SC_HAVEATTR 0x10000U /* Symbol has attributes */
|
||||
|
||||
#define SC_GOTO 0x20000U
|
||||
#define SC_SPADJUSTMENT 0x40000U
|
||||
|
||||
|
||||
|
||||
|
@ -139,6 +140,10 @@ struct SymEntry {
|
|||
Collection *DefsOrRefs;
|
||||
} L;
|
||||
|
||||
struct {
|
||||
unsigned short SPAdjustment;
|
||||
} G;
|
||||
|
||||
/* Register bank offset and offset of the saved copy on stack for
|
||||
** register variables.
|
||||
*/
|
||||
|
|
|
@ -92,7 +92,7 @@ static SymTable* SymTab = 0;
|
|||
static SymTable* TagTab0 = 0;
|
||||
static SymTable* TagTab = 0;
|
||||
static SymTable* LabelTab = 0;
|
||||
|
||||
static SymTable* SPAdjustTab = 0;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -225,6 +225,8 @@ void EnterGlobalLevel (void)
|
|||
|
||||
/* Create and assign the tag table */
|
||||
TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
|
||||
|
||||
SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -405,7 +407,7 @@ void LeaveStructLevel (void)
|
|||
|
||||
|
||||
|
||||
static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
|
||||
SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
|
||||
/* Search for an entry in one table */
|
||||
{
|
||||
/* Get the start of the hash chain */
|
||||
|
@ -660,7 +662,7 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
|
|||
}
|
||||
|
||||
|
||||
DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
|
||||
DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags)
|
||||
/* Add definition or reference to the SymEntry and preserve its attributes */
|
||||
{
|
||||
DefOrRef *DOR;
|
||||
|
@ -677,6 +679,20 @@ DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
|
|||
return DOR;
|
||||
}
|
||||
|
||||
unsigned short FindSPAdjustment (const char* Name)
|
||||
{
|
||||
SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name));
|
||||
|
||||
if (Entry) {
|
||||
printf("L: %s sa: %d\n", Name, Entry->V.G.SPAdjustment);
|
||||
return Entry->V.G.SPAdjustment;
|
||||
}
|
||||
|
||||
Fatal("ICE: No label entry found");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
||||
/* Add a goto label to the label table */
|
||||
{
|
||||
|
@ -728,9 +744,14 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
|||
/* We're processing a label, let's update all gotos encountered
|
||||
** so far
|
||||
*/
|
||||
SymEntry *E;
|
||||
g_userodata();
|
||||
g_defdatalabel (DOR->LateSP_Label);
|
||||
g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
|
||||
E = NewSymEntry (LocalLabelName(DOR->LateSP_Label), SC_SPADJUSTMENT);
|
||||
E->V.G.SPAdjustment = StackPtr - DOR->StackPtr;
|
||||
AddSymEntry (SPAdjustTab, E);
|
||||
|
||||
|
||||
/* Are we jumping into a block with initalization of an object that
|
||||
** has automatic storage duration? Let's emit a warning.
|
||||
|
|
|
@ -136,6 +136,8 @@ SymEntry* FindTagSym (const char* Name);
|
|||
SymEntry* FindStructField (const Type* TypeArray, const char* Name);
|
||||
/* Find a struct field in the fields list */
|
||||
|
||||
unsigned short FindSPAdjustment (const char* Name);
|
||||
/* Search for an entry in the table of SP adjustments */
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
Loading…
Add table
Reference in a new issue