1 /*****************************************************************************/
9 /* (C) 2002 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
39 #include "coptstore.h"
43 /*****************************************************************************/
45 /*****************************************************************************/
49 static void InsertStore (CodeSeg* S, unsigned* IP, LineInfo* LI)
51 CodeEntry* X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, LI);
52 CS_InsertEntry (S, X, (*IP)++);
57 unsigned OptStore1 (CodeSeg* S)
58 /* Search for a call to staxysp. If the ax register is not used later, and
59 * the value is constant, just use the A register and store directly into the
66 /* Generate register info */
69 /* Walk over the entries */
71 while (I < CS_GetEntryCount (S)) {
74 CodeEntry* E = CS_GetEntry (S, I);
76 /* Get the input registers */
77 const RegInfo* RI = E->RI;
79 /* Check for the call */
80 if (CE_IsCallTo (E, "staxysp") &&
81 RegValIsKnown (RI->In.RegA) &&
82 RegValIsKnown (RI->In.RegX) &&
83 RegValIsKnown (RI->In.RegY) &&
84 !RegAXUsed (S, I+1)) {
86 /* Get the register values */
87 unsigned char A = RI->In.RegA;
88 unsigned char X = RI->In.RegX;
89 unsigned char Y = RI->In.RegY;
91 /* Setup other variables */
93 unsigned IP = I + 1; /* Insertion point */
95 /* Replace the store. We will not remove the loads, since this is
96 * too complex and will be done by other optimizer steps.
98 N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI);
99 CS_InsertEntry (S, N, IP++);
100 InsertStore (S, &IP, E->LI);
102 /* Check if we can store one of the other bytes */
104 N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (X), 0, E->LI);
105 CS_InsertEntry (S, N, IP++);
107 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
108 CS_InsertEntry (S, N, IP++);
109 InsertStore (S, &IP, E->LI);
111 /* Remove the call */
114 /* Remember, we had changes */
124 /* Free the register info */
127 /* Return the number of changes made */
133 unsigned OptStore2 (CodeSeg* S)
134 /* Search for a call to steaxysp. If the eax register is not used later, and
135 * the value is constant, just use the A register and store directly into the
140 unsigned Changes = 0;
142 /* Generate register info */
145 /* Walk over the entries */
147 while (I < CS_GetEntryCount (S)) {
150 CodeEntry* E = CS_GetEntry (S, I);
152 /* Get the input registers */
153 const RegInfo* RI = E->RI;
155 /* Check for the call */
156 if (CE_IsCallTo (E, "steaxysp") &&
157 RegValIsKnown (RI->In.RegA) &&
158 RegValIsKnown (RI->In.RegX) &&
159 RegValIsKnown (RI->In.RegY) &&
160 RegValIsKnown (RI->In.SRegLo) &&
161 RegValIsKnown (RI->In.SRegHi) &&
162 !RegEAXUsed (S, I+1)) {
164 /* Get the register values */
165 unsigned char A = RI->In.RegA;
166 unsigned char X = RI->In.RegX;
167 unsigned char Y = RI->In.RegY;
168 unsigned char L = RI->In.SRegLo;
169 unsigned char H = RI->In.SRegHi;
171 /* Setup other variables */
174 unsigned IP = I + 1; /* Insertion point */
176 /* Replace the store. We will not remove the loads, since this is
177 * too complex and will be done by other optimizer steps.
179 N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI);
180 CS_InsertEntry (S, N, IP++);
181 InsertStore (S, &IP, E->LI);
184 /* Check if we can store one of the other bytes */
185 if (A == X && (Done & 0x02) == 0) {
186 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
187 CS_InsertEntry (S, N, IP++);
188 InsertStore (S, &IP, E->LI);
191 if (A == L && (Done & 0x04) == 0) {
192 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
193 CS_InsertEntry (S, N, IP++);
194 InsertStore (S, &IP, E->LI);
197 if (A == H && (Done & 0x08) == 0) {
198 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
199 CS_InsertEntry (S, N, IP++);
200 InsertStore (S, &IP, E->LI);
204 /* Store the second byte */
205 if ((Done & 0x02) == 0) {
206 N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (X), 0, E->LI);
207 CS_InsertEntry (S, N, IP++);
208 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
209 CS_InsertEntry (S, N, IP++);
210 InsertStore (S, &IP, E->LI);
214 /* Check if we can store one of the other bytes */
215 if (X == L && (Done & 0x04) == 0) {
216 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
217 CS_InsertEntry (S, N, IP++);
218 InsertStore (S, &IP, E->LI);
221 if (X == H && (Done & 0x08) == 0) {
222 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
223 CS_InsertEntry (S, N, IP++);
224 InsertStore (S, &IP, E->LI);
228 /* Store the third byte */
229 if ((Done & 0x04) == 0) {
230 N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (L), 0, E->LI);
231 CS_InsertEntry (S, N, IP++);
232 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
233 CS_InsertEntry (S, N, IP++);
234 InsertStore (S, &IP, E->LI);
238 /* Check if we can store one of the other bytes */
239 if (L == H && (Done & 0x08) == 0) {
240 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
241 CS_InsertEntry (S, N, IP++);
242 InsertStore (S, &IP, E->LI);
246 /* Store the fourth byte */
247 if ((Done & 0x08) == 0) {
248 N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (H), 0, E->LI);
249 CS_InsertEntry (S, N, IP++);
250 N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
251 CS_InsertEntry (S, N, IP++);
252 InsertStore (S, &IP, E->LI);
256 /* Remove the call */
259 /* Remember, we had changes */
269 /* Free the register info */
272 /* Return the number of changes made */