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 | |
49 | unsigned 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 | |
116 | unsigned 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 | |