}
static unsigned OptGotoSPAdj (CodeSeg* S)
-/* Remove unnecessary SP adjustment while gotoing
-*/
+/* Optimize SP adjustment for forward 'goto' */
{
unsigned Changes = 0;
unsigned I;
/* Get next entry */
L[0] = CS_GetEntry (S, I);
- /* Check for the sequence */
+ /* Check for the sequence generated by g_lateadjustSP */
if (L[0]->OPC == OP65_PHA &&
CS_GetEntries (S, L+1, I+1, 9) &&
L[1]->OPC == OP65_LDA &&
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);
+ strcmp (L[6]->Arg, "sp+1") == 0 &&
+ L[9]->OPC == OP65_JMP) {
+ adjustment = FindSPAdjustment (L[1]->Arg);
if (adjustment == 0) {
+ /* No SP adjustment needed, remove the whole sequence */
+ CS_DelEntries (S, I, 9);
+ }
+ else if (adjustment >= 65536 - 8) {
+ /* If adjustment is in range [-8, 0) we use decsp* calls */
+ char Buf[20];
+ adjustment = 65536 - adjustment;
+ xsprintf (Buf, sizeof (Buf), "decsp%u", adjustment);
+ X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI);
+ CS_InsertEntry (S, X, I + 9);
+
+ /* Delete the old code */
+ CS_DelEntries (S, I, 9);
+ }
+ else if (adjustment >= 65536 - 255) {
+ /* For range [-255, -8) we have ldy #, jsr subysp */
+ adjustment = 65536 - adjustment;
+ Arg = MakeHexArg (adjustment);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
+ CS_InsertEntry (S, X, I + 9);
+ X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, L[1]->LI);
+ CS_InsertEntry (S, X, I + 10);
+
+ /* Delete the old code */
CS_DelEntries (S, I, 9);
}
else if (adjustment > 255) {
+ /* For ranges [-32768, 255) and (255, 32767) the only modification
+ ** is to replace the absolute with immediate addressing */
Arg = MakeHexArg (adjustment & 0xff);
X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[1]->LI);
- CS_InsertEntry(S, X, I + 1);
+ 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_InsertEntry (S, X, I + 6);
- CS_DelEntry(S, I + 2);
- CS_DelEntry(S, I + 6);
+ /* Delete the old code */
+ CS_DelEntry (S, I + 2);
+ CS_DelEntry (S, I + 6);
}
else if (adjustment > 8) {
+ /* For range (8, 255] we have ldy #0, jsr addysp */
Arg = MakeHexArg (adjustment & 0xff);
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
- CS_InsertEntry (S, X, I);
+ CS_InsertEntry (S, X, I + 9);
X = NewCodeEntry (OP65_JSR, AM65_ABS, "addysp", 0, L[1]->LI);
- CS_InsertEntry (S, X, I + 1);
+ CS_InsertEntry (S, X, I + 10);
- CS_DelEntries(S, I + 2, 9);
+ /* Delete the old code */
+ CS_DelEntries (S, I, 9);
}
else {
+ /* If adjustment is in range (0, 8] we use incsp* calls */
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_InsertEntry (S, X, I + 9);
- CS_DelEntries(S, I + 1, 9);
+ /* Delete the old code */
+ CS_DelEntries (S, I, 9);
}
/* Regenerate register info */
CS_GenRegInfo (S);
/* Remember we had changes */
Changes++;
+
} else {
/* Next entry */
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 */
/* Create and assign the tag table */
TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
+ /* Create and assign the table of SP adjustment symbols */
SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
}
unsigned short FindSPAdjustment (const char* Name)
{
+/* Search for an entry in the table of SP adjustments */
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;
+ if (!Entry) {
+ Internal ("No SP adjustment label entry found");
}
- Fatal("ICE: No label entry found");
-
- return 0;
+ return Entry->V.G.SPAdjustment;
}
SymEntry* AddLabelSym (const char* Name, unsigned Flags)
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);
+
+ /* Optimizer will need the information about the value of SP adjustment
+ ** later, so let's preserve it. */
+ 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.
*/