#include "error.h"
#include "global.h"
#include "output.h"
-
+#include "symtab.h"
/*****************************************************************************/
return Changes;
}
+static unsigned OptGotoSPAdj (CodeSeg* S)
+/* Optimize SP adjustment for forward 'goto' */
+{
+ 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 generated by g_lateadjustSP */
+ 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) {
+ 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);
+ Arg = MakeHexArg (adjustment >> 8);
+ X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[5]->LI);
+ CS_InsertEntry (S, X, 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 #, jsr addysp */
+ Arg = MakeHexArg (adjustment & 0xff);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
+ CS_InsertEntry (S, X, I + 9);
+ X = NewCodeEntry (OP65_JSR, AM65_ABS, "addysp", 0, L[1]->LI);
+ CS_InsertEntry (S, X, I + 10);
+
+ /* 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 + 9);
+
+ /* Delete the old code */
+ CS_DelEntries (S, I, 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 */
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 };
static OptFunc DOptPtrLoad15 = { OptPtrLoad15, "OptPtrLoad15", 86, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrLoad16 = { OptPtrLoad16, "OptPtrLoad16", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrLoad17 = { OptPtrLoad17, "OptPtrLoad17", 190, 0, 0, 0, 0, 0 };
+static OptFunc DOptPtrLoad18 = { OptPtrLoad18, "OptPtrLoad18", 100, 0, 0, 0, 0, 0 };
+static OptFunc DOptPtrLoad19 = { OptPtrLoad19, "OptPtrLoad19", 65, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 65, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 65, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 100, 0, 0, 0, 0, 0 };
&DOptDeadJumps,
&DOptDecouple,
&DOptDupLoads,
+ &DOptGotoSPAdj,
&DOptIndLoads1,
&DOptIndLoads2,
&DOptJumpCascades,
&DOptPtrLoad15,
&DOptPtrLoad16,
&DOptPtrLoad17,
+ &DOptPtrLoad18,
+ &DOptPtrLoad19,
&DOptPtrLoad2,
&DOptPtrLoad3,
&DOptPtrLoad4,
OptFunc* F = FindOptFunc (Name);
if (F == 0) {
/* Not found */
- AbEnd ("Optimization step `%s' not found", Name);
+ AbEnd ("Optimization step '%s' not found", Name);
}
return F;
}
/* Output a header line */
if (Step == 0) {
/* Initial output */
- WriteOutput ("Initial code for function `%s':\n",
+ WriteOutput ("Initial code for function '%s':\n",
S->Func? S->Func->Name : "<global>");
} else {
- WriteOutput ("Code after applying `%s':\n", Step);
+ WriteOutput ("Code after applying '%s':\n", Step);
}
/* Output the code segment */
{
unsigned Changes = 0;
+ Changes += RunOptFunc (S, &DOptGotoSPAdj, 1);
Changes += RunOptFunc (S, &DOptStackPtrOps, 5);
Changes += RunOptFunc (S, &DOptPtrStore1, 1);
Changes += RunOptFunc (S, &DOptPtrStore2, 1);
Changes += RunOptFunc (S, &DOptPtrLoad5, 1);
Changes += RunOptFunc (S, &DOptPtrLoad6, 1);
Changes += RunOptFunc (S, &DOptPtrLoad7, 1);
+ Changes += RunOptFunc (S, &DOptPtrLoad18, 1); /* Before OptPtrLoad11 */
Changes += RunOptFunc (S, &DOptPtrLoad11, 1);
Changes += RunOptFunc (S, &DOptPtrLoad12, 1);
Changes += RunOptFunc (S, &DOptPtrLoad13, 1);
Changes += RunOptFunc (S, &DOptPtrLoad15, 1);
Changes += RunOptFunc (S, &DOptPtrLoad16, 1);
Changes += RunOptFunc (S, &DOptPtrLoad17, 1);
+ Changes += RunOptFunc (S, &DOptPtrLoad19, 1);
Changes += RunOptFunc (S, &DOptBNegAX1, 1);
Changes += RunOptFunc (S, &DOptBNegAX2, 1);
Changes += RunOptFunc (S, &DOptBNegAX3, 1);
/* Print the name of the function we are working on */
if (S->Func) {
- Print (stdout, 1, "Running optimizer for function `%s'\n", S->Func->Name);
+ Print (stdout, 1, "Running optimizer for function '%s'\n", S->Func->Name);
} else {
Print (stdout, 1, "Running optimizer for global code segment\n");
}