1/*****************************************************************************/
2/* */
3/* coptpush.c */
4/* */
5/* Optimize push sequences */
6/* */
7/* */
8/* */
9/* (C) 2001-2012, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
15/* This software is provided 'as-is', without any expressed or implied */
16/* warranty. In no event will the authors be held liable for any damages */
17/* arising from the use of this software. */
18/* */
19/* Permission is granted to anyone to use this software for any purpose, */
20/* including commercial applications, and to alter it and redistribute it */
21/* freely, subject to the following restrictions: */
22/* */
23/* 1. The origin of this software must not be misrepresented; you must not */
24/* claim that you wrote the original software. If you use this software */
25/* in a product, an acknowledgment in the product documentation would be */
26/* appreciated but is not required. */
27/* 2. Altered source versions must be plainly marked as such, and must not */
28/* be misrepresented as being the original software. */
29/* 3. This notice may not be removed or altered from any source */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36/* cc65 */
37#include "codeent.h"
38#include "codeinfo.h"
39#include "coptpush.h"
40
41
42
43/*****************************************************************************/
44/* Code */
45/*****************************************************************************/
46
47
48
49unsigned OptPush1 (CodeSeg* S)
50/* Given a sequence
51**
52** jsr ldaxysp
53** jsr pushax
54**
55** If a/x are not used later, and Y is known, replace that by
56**
57** ldy #xx+2
58** jsr pushwysp
59**
60** saving 3 bytes and several cycles.
61*/
62{
63 unsigned I;
64 unsigned Changes = 0;
65
66 /* Walk over the entries */
67 I = 0;
68 while (I < CS_GetEntryCount (S)) {
69
70 CodeEntry* L[2];
71
72 /* Get next entry */
73 L[0] = CS_GetEntry (S, I);
74
75 /* Check for the sequence */
76 if (CE_IsCallTo (L[0], "ldaxysp") &&
77 RegValIsKnown (L[0]->RI->In.RegY) &&
78 L[0]->RI->In.RegY < 0xFE &&
79 (L[1] = CS_GetNextEntry (S, I)) != 0 &&
80 !CE_HasLabel (L[1]) &&
81 CE_IsCallTo (L[1], "pushax") &&
82 !RegAXUsed (S, I+2)) {
83
84 /* Insert new code behind the pushax */
85 const char* Arg;
86 CodeEntry* X;
87
88 /* ldy #xx+1 */
89 Arg = MakeHexArg (L[0]->RI->In.RegY+2);
90 X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[0]->LI);
91 CS_InsertEntry (S, X, I+2);
92
93 /* jsr pushwysp */
94 X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwysp", 0, L[1]->LI);
95 CS_InsertEntry (S, X, I+3);
96
97 /* Delete the old code */
98 CS_DelEntries (S, I, 2);
99
100 /* Remember, we had changes */
101 ++Changes;
102
103 }
104
105 /* Next entry */
106 ++I;
107
108 }
109
110 /* Return the number of changes made */
111 return Changes;
112}
113
114
115
116unsigned OptPush2 (CodeSeg* S)
117/* A sequence
118**
119** jsr ldaxidx
120** jsr pushax
121**
122** may get replaced by
123**
124** jsr pushwidx
125*/
126{
127 unsigned I;
128 unsigned Changes = 0;
129
130 /* Walk over the entries */
131 I = 0;
132 while (I < CS_GetEntryCount (S)) {
133
134 CodeEntry* L[2];
135
136 /* Get next entry */
137 L[0] = CS_GetEntry (S, I);
138
139 /* Check for the sequence */
140 if (CE_IsCallTo (L[0], "ldaxidx") &&
141 (L[1] = CS_GetNextEntry (S, I)) != 0 &&
142 !CE_HasLabel (L[1]) &&
143 CE_IsCallTo (L[1], "pushax")) {
144
145 /* Insert new code behind the pushax */
146 CodeEntry* X;
147
148 /* jsr pushwidx */
149 X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwidx", 0, L[1]->LI);
150 CS_InsertEntry (S, X, I+2);
151
152 /* Delete the old code */
153 CS_DelEntries (S, I, 2);
154
155 /* Remember, we had changes */
156 ++Changes;
157
158 }
159
160 /* Next entry */
161 ++I;
162
163 }
164
165 /* Return the number of changes made */
166 return Changes;
167}
168