+/*****************************************************************************/
+/* Optimize stack pointer ops */
+/*****************************************************************************/
+
+
+
+static unsigned IsDecSP (const CodeEntry* E)
+/* Check if this is an insn that decrements the stack pointer. If so, return
+ * the decrement. If not, return zero.
+ * The function expects E to be a subroutine call.
+ */
+{
+ if (strncmp (E->Arg, "decsp", 5) == 0) {
+ if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
+ return (E->Arg[5] - '0');
+ }
+ } else if (strcmp (E->Arg, "subysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
+ return E->RI->In.RegY;
+ }
+
+ /* If we come here, it's not a decsp op */
+ return 0;
+}
+
+
+
+static unsigned OptStackPtrOps (CodeSeg* S)
+/* Merge adjacent calls to decsp into one. NOTE: This function won't merge all
+ * known cases!
+ */
+{
+ unsigned Changes = 0;
+ unsigned I;
+
+ /* Generate register info for the following step */
+ CS_GenRegInfo (S);
+
+ /* Walk over the entries */
+ I = 0;
+ while (I < CS_GetEntryCount (S)) {
+
+ unsigned Dec1;
+ unsigned Dec2;
+ const CodeEntry* N;
+
+ /* Get the next entry */
+ const CodeEntry* E = CS_GetEntry (S, I);
+
+ /* Check for decspn or subysp */
+ if (E->OPC == OP65_JSR &&
+ (Dec1 = IsDecSP (E)) > 0 &&
+ (N = CS_GetNextEntry (S, I)) != 0 &&
+ (Dec2 = IsDecSP (N)) > 0 &&
+ (Dec1 += Dec2) <= 255 &&
+ !CE_HasLabel (N)) {
+
+ CodeEntry* X;
+ char Buf[20];
+
+ /* We can combine the two */
+ if (Dec1 <= 8) {
+ /* Insert a call to decsp */
+ xsprintf (Buf, sizeof (Buf), "decsp%u", Dec1);
+ X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, N->LI);
+ CS_InsertEntry (S, X, I+2);
+ } else {
+ /* Insert a call to subysp */
+ const char* Arg = MakeHexArg (Dec1);
+ X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI);
+ CS_InsertEntry (S, X, I+2);
+ X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, N->LI);
+ CS_InsertEntry (S, X, I+3);
+ }
+
+ /* Delete the old code */
+ CS_DelEntries (S, I, 2);
+
+ /* Regenerate register info */
+ CS_GenRegInfo (S);
+
+ /* Remember we had changes */
+ ++Changes;
+
+ } else {
+
+ /* Next entry */
+ ++I;
+ }
+
+ }
+
+ /* Free register info */
+ CS_FreeRegInfo (S);
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+
+