]> git.sur5r.net Git - cc65/blob - src/cc65/coptsize.c
Since we have now builtin search paths, we need to be able to forget them,
[cc65] / src / cc65 / coptsize.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 coptsize.c                                */
4 /*                                                                           */
5 /*                              Size optimizations                           */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2009, 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 #include <stdlib.h>
37
38 /* common */
39 #include "cpu.h"
40
41 /* cc65 */
42 #include "codeent.h"
43 #include "codeinfo.h"
44 #include "coptsize.h"
45 #include "reginfo.h"
46
47
48
49 /*****************************************************************************/
50 /*                                   Data                                    */
51 /*****************************************************************************/
52
53
54
55 /* Flags for CallDesc */
56 #define F_NONE          0x0000U /* No extra flags */
57 #define F_SLOWER        0x0001U /* Function call is slower */
58
59 typedef struct CallDesc CallDesc;
60 struct CallDesc {
61     const char* LongFunc;       /* Long function name */
62     RegContents Regs;           /* Register contents */
63     unsigned    Flags;          /* Flags from above */
64     const char* ShortFunc;      /* Short function name */
65 };
66
67 /* Note: The table is sorted. If there is more than one entry with the same
68  * name, entries are sorted best match first, so when searching linear for
69  * a match, the first one can be used because it is also the best one (or
70  * at least none of the following ones are better).
71  * Note^2: Ptr1 and Tmp1 aren't evaluated, because runtime routines don't
72  * expect parameters here.
73  */
74 static const CallDesc CallTable [] = {
75     /* Name          A register      X register     Y register     flags     replacement */
76     {
77         "addeqysp",
78         {
79             /*     A               X               Y             SRegLo   */
80             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,
81             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
82             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
83         },
84         F_NONE,
85         "addeq0sp"
86     },{
87         "laddeq",
88         {
89             /*     A               X               Y             SRegLo   */
90                          1,              0, UNKNOWN_REGVAL,              0,
91             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
92                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
93         },
94         F_NONE,
95         "laddeq1"
96     },{
97         "laddeq",
98         {
99             /*     A               X               Y             SRegLo   */
100             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,              0,
101             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
102                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
103         },
104         F_NONE,
105         "laddeqa"
106     },{
107         "laddeqysp",
108         {
109             /*     A               X               Y             SRegLo   */
110             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,
111             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
112             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
113         },
114         F_NONE,
115         "laddeq0sp"
116     },{
117         "ldaxidx",
118         {
119             /*     A               X               Y             SRegLo   */
120             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, UNKNOWN_REGVAL,
121             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
122             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
123         },
124         F_NONE,
125         "ldaxi"
126     },{
127         "ldaxysp",
128         {
129             /*     A               X               Y             SRegLo   */
130             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, UNKNOWN_REGVAL,
131             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
132             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
133         },
134         F_NONE,
135         "ldax0sp"
136     },{
137         "ldeaxidx",
138         {
139             /*     A               X               Y             SRegLo   */
140             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, UNKNOWN_REGVAL,
141             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
142             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
143         },
144         F_NONE,
145         "ldeaxi"
146     },{
147         "ldeaxysp",
148         {
149             /*     A               X               Y             SRegLo   */
150             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, UNKNOWN_REGVAL,
151             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
152             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
153         },
154         F_NONE,
155         "ldeax0sp"
156     },{
157         "leaaxsp",
158         {
159             /*     A               X               Y             SRegLo   */
160             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
161             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
162             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
163         },
164         F_NONE,
165         "leaa0sp"
166     },{
167         "lsubeq",
168         {
169             /*     A               X               Y             SRegLo   */
170                          1,              0, UNKNOWN_REGVAL,              0,
171             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
172                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
173         },
174         F_NONE,
175         "lsubeq1"
176     },{
177         "lsubeq",
178         {
179             /*     A               X               Y             SRegLo   */
180             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,              0,
181             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
182                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
183         },
184         F_NONE,
185         "lsubeqa"
186     },{
187         "lsubeqysp",
188         {
189             /*     A               X               Y             SRegLo   */
190             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,
191             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
192             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
193         },
194         F_NONE,
195         "lsubeq0sp"
196     },{
197         "pusha",
198         {
199             /*     A               X               Y             SRegLo   */
200                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
201             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
202             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
203         },
204         F_SLOWER,
205         "pushc0"
206     },{
207         "pusha",
208         {
209             /*     A               X               Y             SRegLo   */
210                          1, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
211             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
212             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
213         },
214         F_SLOWER,
215         "pushc1"
216     },{
217         "pusha",
218         {
219             /*     A               X               Y             SRegLo   */
220                          2, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
221             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
222             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
223         },
224         F_SLOWER,
225         "pushc2"
226     },{
227         "pushax",
228         {
229             /*     A               X               Y             SRegLo   */
230                          0,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
231             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
232             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
233         },
234         F_NONE,
235         "push0"
236     },{
237         "pushax",
238         {
239             /*     A               X               Y             SRegLo   */
240                          1,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
241             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
242             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
243         },
244         F_SLOWER,
245         "push1"
246     },{
247         "pushax",
248         {
249             /*     A               X               Y             SRegLo   */
250                          2,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
251             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
252             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
253         },
254         F_SLOWER,
255         "push2"
256     },{
257         "pushax",
258         {
259             /*     A               X               Y             SRegLo   */
260                          3,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
261             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
262             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
263         },
264         F_SLOWER,
265         "push3"
266     },{
267         "pushax",
268         {
269             /*     A               X               Y             SRegLo   */
270                          4,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
271             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
272             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
273         },
274         F_SLOWER,
275         "push4"
276     },{
277         "pushax",
278         {
279             /*     A               X               Y             SRegLo   */
280                          5,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
281             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
282             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
283         },
284         F_SLOWER,
285         "push5"
286     },{
287         "pushax",
288         {
289             /*     A               X               Y             SRegLo   */
290                          6,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
291             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
292             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
293         },
294         F_SLOWER,
295         "push6"
296     },{
297         "pushax",
298         {
299             /*     A               X               Y             SRegLo   */
300                          7,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
301             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
302             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
303         },
304         F_SLOWER,
305         "push7"
306     },{
307         "pushax",
308         {
309             /*     A               X               Y             SRegLo   */
310             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
311             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
312             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
313         },
314         F_NONE,
315         "pusha0"
316     },{
317         "pushax",
318         {
319             /*     A               X               Y             SRegLo   */
320             UNKNOWN_REGVAL,           0xFF, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
321             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
322             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
323         },
324         F_SLOWER,
325         "pushaFF"
326     },{
327         "pushaysp",
328         {
329             /*     A               X               Y             SRegLo   */
330             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,
331             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
332             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
333         },
334         F_NONE,
335         "pusha0sp"
336     },{
337         "pusheax",
338         {
339             /*     A               X               Y             SRegLo   */
340             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
341             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
342                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
343         },
344         F_NONE,
345         "push0ax"
346     },{
347         "pushwidx",
348         {
349             /*     A               X               Y             SRegLo   */
350             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              1, UNKNOWN_REGVAL,
351             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
352             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
353         },
354         F_NONE,
355         "pushw"
356     },{
357         "pushwysp",
358         {
359             /*     A               X               Y             SRegLo   */
360             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              3, UNKNOWN_REGVAL,
361             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
362             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
363         },
364         F_NONE,
365         "pushw0sp"
366     },{
367         "staxysp",
368         {
369             /*     A               X               Y             SRegLo   */
370             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,
371             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
372             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
373         },
374         F_NONE,
375         "stax0sp"
376     },{
377         "steaxysp",
378         {
379             /*     A               X               Y             SRegLo   */
380             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,
381             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
382             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
383         },
384         F_NONE,
385         "steax0sp"
386     },{
387         "subeqysp",
388         {
389             /*     A               X               Y             SRegLo   */
390             UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL,
391             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
392             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
393         },
394         F_NONE,
395         "subeq0sp"
396     },{
397         "tosaddax",
398         {
399             /*     A               X               Y             SRegLo   */
400             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
401             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
402             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
403         },
404         F_NONE,
405         "tosadda0"
406     },{
407         "tosaddeax",
408         {
409             /*     A               X               Y             SRegLo   */
410             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
411             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
412                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
413         },
414         F_NONE,
415         "tosadd0ax"
416     },{
417         "tosandax",
418         {
419             /*     A               X               Y             SRegLo   */
420             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
421             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
422             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
423         },
424         F_NONE,
425         "tosanda0"
426     },{
427         "tosandeax",
428         {
429             /*     A               X               Y             SRegLo   */
430             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
431             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
432                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
433         },
434         F_NONE,
435         "tosand0ax"
436     },{
437         "tosdivax",
438         {
439             /*     A               X               Y             SRegLo   */
440             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
441             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
442             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
443         },
444         F_NONE,
445         "tosdiva0"
446     },{
447         "tosdiveax",
448         {
449             /*     A               X               Y             SRegLo   */
450             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
451             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
452                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
453         },
454         F_NONE,
455         "tosdiv0ax"
456     },{
457         "toseqax",
458         {
459             /*     A               X               Y             SRegLo   */
460                          0,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
461             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
462             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
463         },
464         F_NONE,
465         "toseq00"
466     },{
467         "toseqax",
468         {
469             /*     A               X               Y             SRegLo   */
470             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
471             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
472             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
473         },
474         F_NONE,
475         "toseqa0"
476     },{
477         "tosgeax",
478         {
479             /*     A               X               Y             SRegLo   */
480                          0,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
481             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
482             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
483         },
484         F_NONE,
485         "tosge00"
486     },{
487         "tosgeax",
488         {
489             /*     A               X               Y             SRegLo   */
490             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
491             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
492             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
493         },
494         F_NONE,
495         "tosgea0"
496     },{
497         "tosgtax",
498         {
499             /*     A               X               Y             SRegLo   */
500                          0,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
501             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
502             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
503         },
504         F_NONE,
505         "tosgt00"
506     },{
507         "tosgtax",
508         {
509             /*     A               X               Y             SRegLo   */
510             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
511             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
512             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
513         },
514         F_NONE,
515         "tosgta0"
516     },{
517         "tosicmp",
518         {
519             /*     A               X               Y             SRegLo   */
520             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
521             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
522             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
523         },
524         F_NONE,
525         "tosicmp0"
526     },{
527         "tosleax",
528         {
529             /*     A               X               Y             SRegLo   */
530                          0,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
531             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
532             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
533         },
534         F_NONE,
535         "tosle00"
536     },{
537         "tosleax",
538         {
539             /*     A               X               Y             SRegLo   */
540             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
541             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
542             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
543         },
544         F_NONE,
545         "toslea0"
546     },{
547         "tosltax",
548         {
549             /*     A               X               Y             SRegLo   */
550                          0,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
551             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
552             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
553         },
554         F_NONE,
555         "toslt00"
556     },{
557         "tosltax",
558         {
559             /*     A               X               Y             SRegLo   */
560             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
561             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
562             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
563         },
564         F_NONE,
565         "toslta0"
566     },{
567         "tosmodax",
568         {
569             /*     A               X               Y             SRegLo   */
570             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
571             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
572             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
573         },
574         F_NONE,
575         "tosmoda0"
576     },{
577         "tosmodeax",
578         {
579             /*     A               X               Y             SRegLo   */
580             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
581             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
582                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
583         },
584         F_NONE,
585         "tosmod0ax"
586     },{
587         "tosmulax",
588         {
589             /*     A               X               Y             SRegLo   */
590             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
591             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
592             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
593         },
594         F_NONE,
595         "tosmula0"
596     },{
597         "tosmuleax",
598         {
599             /*     A               X               Y             SRegLo   */
600             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
601             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
602                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
603         },
604         F_NONE,
605         "tosmul0ax"
606     },{
607         "tosneax",
608         {
609             /*     A               X               Y             SRegLo   */
610             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
611             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
612             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
613         },
614         F_NONE,
615         "tosnea0"
616     },{
617         "tosorax",
618         {
619             /*     A               X               Y             SRegLo   */
620             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
621             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
622             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
623         },
624         F_NONE,
625         "tosora0"
626     },{
627         "tosoreax",
628         {
629             /*     A               X               Y             SRegLo   */
630             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
631             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
632                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
633         },
634         F_NONE,
635         "tosor0ax"
636     },{
637         "tosrsubax",
638         {
639             /*     A               X               Y             SRegLo   */
640             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
641             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
642             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
643         },
644         F_NONE,
645         "tosrsuba0"
646     },{
647         "tosrsubeax",
648         {
649             /*     A               X               Y             SRegLo   */
650             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
651             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
652                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
653         },
654         F_NONE,
655         "tosrsub0ax"
656     },{
657         "tossubax",
658         {
659             /*     A               X               Y             SRegLo   */
660             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
661             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
662             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
663         },
664         F_NONE,
665         "tossuba0"
666     },{
667         "tossubeax",
668         {
669             /*     A               X               Y             SRegLo   */
670             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
671             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
672                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
673         },
674         F_NONE,
675         "tossub0ax"
676     },{
677         "tosudivax",
678         {
679             /*     A               X               Y             SRegLo   */
680             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
681             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
682             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
683         },
684         F_NONE,
685         "tosudiva0"
686     },{
687         "tosudiveax",
688         {
689             /*     A               X               Y             SRegLo   */
690             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
691             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
692                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
693         },
694         F_NONE,
695         "tosudiv0ax"
696     },{
697         "tosugeax",
698         {
699             /*     A               X               Y             SRegLo   */
700             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
701             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
702             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
703         },
704         F_NONE,
705         "tosugea0"
706     },{
707         "tosugtax",
708         {
709             /*     A               X               Y             SRegLo   */
710             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
711             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
712             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
713         },
714         F_NONE,
715         "tosugta0"
716     },{
717         "tosuleax",
718         {
719             /*     A               X               Y             SRegLo   */
720             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
721             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
722             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
723         },
724         F_NONE,
725         "tosulea0"
726     },{
727         "tosultax",
728         {
729             /*     A               X               Y             SRegLo   */
730             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
731             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
732             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
733         },
734         F_NONE,
735         "tosulta0"
736     },{
737         "tosumodax",
738         {
739             /*     A               X               Y             SRegLo   */
740             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
741             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
742             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
743         },
744         F_NONE,
745         "tosumoda0"
746     },{
747         "tosumodeax",
748         {
749             /*     A               X               Y             SRegLo   */
750             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
751             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
752                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
753         },
754         F_NONE,
755         "tosumod0ax"
756     },{
757         "tosumulax",
758         {
759             /*     A               X               Y             SRegLo   */
760             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
761             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
762             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
763         },
764         F_NONE,
765         "tosumula0"
766     },{
767         "tosumuleax",
768         {
769             /*     A               X               Y             SRegLo   */
770             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
771             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
772                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
773         },
774         F_NONE,
775         "tosumul0ax"
776     },{
777         "tosxorax",
778         {
779             /*     A               X               Y             SRegLo   */
780             UNKNOWN_REGVAL,              0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
781             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
782             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
783         },
784         F_NONE,
785         "tosxora0"
786     },{
787         "tosxoreax",
788         {
789             /*     A               X               Y             SRegLo   */
790             UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,              0,
791             /*   SRegHi          Ptr1Lo          Ptr1Hi           Tmp1    */
792                          0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
793         },
794         F_NONE,
795         "tosxor0ax"
796     },
797
798 };
799 #define CALL_COUNT (sizeof(CallTable) / sizeof(CallTable[0]))
800
801
802
803 /*****************************************************************************/
804 /*                                  Helpers                                  */
805 /*****************************************************************************/
806
807
808
809 static const CallDesc* FindCall (const char* Name)
810 /* Find the function with the given name. Return a pointer to the table entry
811  * or NULL if the function was not found.
812  */
813 {
814     /* Do a binary search */
815     int First = 0;
816     int Last = CALL_COUNT - 1;
817     int Found = 0;
818
819     while (First <= Last) {
820
821         /* Set current to mid of range */
822         int Current = (Last + First) / 2;
823
824         /* Do a compare */
825         int Result = strcmp (CallTable[Current].LongFunc, Name);
826         if (Result < 0) {
827             First = Current + 1;
828         } else {
829             Last = Current - 1;
830             if (Result == 0) {
831                 /* Found. Repeat the procedure until the first of all entries
832                  * with the same name is found.
833                  */
834                 Found = 1;
835             }
836         }
837     }
838
839     /* Return the first entry if found, or NULL otherwise */
840     return Found? &CallTable[First] : 0;
841 }
842
843
844
845 static int RegMatch (short Expected, short Actual)
846 /* Check for a register match. If Expected has a value, it must be identical
847  * to Actual.
848  */
849 {
850     return RegValIsUnknown (Expected) || (Expected == Actual);
851 }
852
853
854
855 /*****************************************************************************/
856 /*                                   Code                                    */
857 /*****************************************************************************/
858
859
860
861 unsigned OptSize1 (CodeSeg* S)
862 /* Do size optimization by calling special subroutines that preload registers.
863  * This routine does not work standalone, it needs a following register load
864  * removal pass.
865  */
866 {
867     CodeEntry* E;
868     unsigned Changes = 0;
869     unsigned I;
870
871     /* Are we optimizing for size */
872     int OptForSize = (S->CodeSizeFactor < 100);
873
874     /* Generate register info for the following step */
875     CS_GenRegInfo (S);
876
877     /* Walk over the entries */
878     I = 0;
879     while (I < CS_GetEntryCount (S)) {
880
881         const CallDesc* D;
882
883         /* Get next entry */
884         E = CS_GetEntry (S, I);
885
886         /* Check if it's a subroutine call */
887         if (E->OPC == OP65_JSR && (D = FindCall (E->Arg)) != 0) {
888
889             /* Get input register info for this insn */
890             const RegContents* In = &E->RI->In;
891
892             /* FindCall finds the first entry that matches our function name.
893              * The names are listed in "best match" order, so search for the
894              * first one, that fulfills our conditions.
895              */
896             while (1) {
897
898                 /* Check the registers and allow slower code only if
899                  * optimizing for size.
900                  */
901                 if ((OptForSize || (D->Flags & F_SLOWER) == 0)          &&
902                     RegMatch (D->Regs.RegA,    In->RegA)                &&
903                     RegMatch (D->Regs.RegX,    In->RegX)                &&
904                     RegMatch (D->Regs.RegY,    In->RegY)                &&
905                     RegMatch (D->Regs.SRegLo,  In->SRegLo)              &&
906                     RegMatch (D->Regs.SRegHi,  In->SRegHi)) {
907
908                     /* Ok, match for all conditions */
909                     CodeEntry* X;
910                     X = NewCodeEntry (E->OPC, E->AM, D->ShortFunc, 0, E->LI);
911                     CS_InsertEntry (S, X, I+1);
912                     CS_DelEntry (S, I);
913
914                     /* Remember that we had changes */
915                     ++Changes;
916
917                     /* Done */
918                     break;
919                 }
920
921                 /* Next table entry, bail out if next entry not valid */
922                 if (++D >= CallTable + CALL_COUNT ||
923                     strcmp (D->LongFunc, E->Arg) != 0) {
924                     /* End of table or entries reached */
925                     break;
926                 }
927             }
928         }
929
930         /* Next entry */
931         ++I;
932
933     }
934
935     /* Free register info */
936     CS_FreeRegInfo (S);
937
938     /* Return the number of changes made */
939     return Changes;
940 }
941
942
943
944 unsigned OptSize2 (CodeSeg* S)
945 /* Do size optimization by using shorter code sequences, even if this
946  * introduces relations between instructions. This step must be one of the
947  * last steps, because it makes further work much more difficult.
948  */
949 {
950     unsigned Changes = 0;
951     unsigned I;
952
953     /* Generate register info for the following step */
954     CS_GenRegInfo (S);
955
956     /* Walk over the entries */
957     I = 0;
958     while (I < CS_GetEntryCount (S)) {
959
960         /* Get next entry */
961         CodeEntry* E = CS_GetEntry (S, I);
962
963         /* Get the input registers */
964         const RegContents* In = &E->RI->In;
965
966         /* Assume we have no replacement */
967         CodeEntry* X = 0;
968
969         /* Check the instruction */
970         switch (E->OPC) {
971
972             case OP65_LDA:
973                 if (CE_IsConstImm (E)) {
974                     short Val = (short) E->Num;
975                     if (Val == In->RegX) {
976                         X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI);
977                     } else if (Val == In->RegY) {
978                         X = NewCodeEntry (OP65_TYA, AM65_IMP, 0, 0, E->LI);
979                     } else if (RegValIsKnown (In->RegA) && (CPUIsets[CPU] & CPU_ISET_65SC02) != 0) {
980                         if (Val == ((In->RegA - 1) & 0xFF)) {
981                             X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI);
982                         } else if (Val == ((In->RegA + 1) & 0xFF)) {
983                             X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
984                         }
985                     }
986                 }
987                 break;
988
989             case OP65_LDX:
990                 if (CE_IsConstImm (E)) {
991                     short Val = (short) E->Num;
992                     if (RegValIsKnown (In->RegX) && Val == ((In->RegX - 1) & 0xFF)) {
993                         X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI);
994                     } else if (RegValIsKnown (In->RegX) && Val == ((In->RegX + 1) & 0xFF)) {
995                         X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
996                     } else if (Val == In->RegA) {
997                         X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
998                     }
999                 }
1000                 break;
1001
1002             case OP65_LDY:
1003                 if (CE_IsConstImm (E)) {
1004                     short Val = (short) E->Num;
1005                     if (RegValIsKnown (In->RegY) && Val == ((In->RegY - 1) & 0xFF)) {
1006                         X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
1007                     } else if (RegValIsKnown (In->RegY) && Val == ((In->RegY + 1) & 0xFF)) {
1008                         X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI);
1009                     } else if (Val == In->RegA) {
1010                         X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI);
1011                     }
1012                 }
1013                 break;
1014
1015             default:
1016                 /* Avoid gcc warnings */
1017                 break;
1018
1019         }
1020
1021         /* Insert the replacement if we have one */
1022         if (X) {
1023             CS_InsertEntry (S, X, I+1);
1024             CS_DelEntry (S, I);
1025             ++Changes;
1026         }
1027
1028         /* Next entry */
1029         ++I;
1030
1031     }
1032
1033     /* Free register info */
1034     CS_FreeRegInfo (S);
1035
1036     /* Return the number of changes made */
1037     return Changes;
1038 }
1039
1040
1041