/*****************************************************************************/
/* */
-/* coptsize.c */
+/* coptsize.c */
/* */
/* Size optimizations */
/* */
/* */
/* */
-/* (C) 2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@cc65.org */
+/* (C) 2002-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <stdlib.h>
+/* common */
+#include "cpu.h"
+
/* cc65 */
#include "codeent.h"
#include "codeinfo.h"
-#include "cpu.h"
#include "coptsize.h"
+#include "reginfo.h"
+/* Flags for CallDesc */
+#define F_NONE 0x0000U /* No extra flags */
+#define F_SLOWER 0x0001U /* Function call is slower */
+
typedef struct CallDesc CallDesc;
struct CallDesc {
- const char* LongFunc; /* Long function name */
- short A, X, Y; /* Register contents */
- const char* ShortFunc; /* Short function name */
+ const char* LongFunc; /* Long function name */
+ RegContents Regs; /* Register contents */
+ unsigned Flags; /* Flags from above */
+ const char* ShortFunc; /* Short function name */
};
/* Note: The table is sorted. If there is more than one entry with the same
- * name, entries are sorted best match first, so when searching linear for
- * a match, the first one can be used because it is also the best one (or
- * at least none of the following ones are better).
- */
+** name, entries are sorted best match first, so when searching linear for
+** a match, the first one can be used because it is also the best one (or
+** at least none of the following ones are better).
+** Note^2: Ptr1 and Tmp1 aren't evaluated, because runtime routines don't
+** expect parameters here.
+*/
static const CallDesc CallTable [] = {
- { "addeqysp", -1, -1, 0, "addeq0sp" },
- { "laddeqysp", -1, -1, 0, "laddeq0sp" },
- { "ldaxysp", -1, -1, 1, "ldax0sp" },
- { "ldeaxidx", -1, -1, 3, "ldeaxi" },
- { "ldeaxysp", -1, -1, 3, "ldeax0sp" },
- { "pusha", 0, -1, -1, "pushc0" },
- { "pusha", 1, -1, -1, "pushc1" },
- { "pusha", 2, -1, -1, "pushc2" },
- { "pushax", 0, 0, -1, "push0" },
- { "pushax", 1, 0, -1, "push1" },
- { "pushax", 2, 0, -1, "push2" },
- { "pushax", 3, 0, -1, "push3" },
- { "pushax", 4, 0, -1, "push4" },
- { "pushax", 5, 0, -1, "push5" },
- { "pushax", 6, 0, -1, "push6" },
- { "pushax", 7, 0, -1, "push7" },
- { "pushax", -1, 0, -1, "pusha0" },
- { "pushax", -1, 0xFF, -1, "pushaFF" },
- { "pushaysp", -1, -1, 0, "pusha0sp" },
- { "staxysp", -1, -1, 0, "stax0sp" },
- { "tosaddax", -1, 0, -1, "tosadda0" },
- { "tosandax", -1, 0, -1, "tosanda0" },
- { "tosdivax", -1, 0, -1, "tosdiva0" },
- { "toseqax", -1, 0, -1, "toseqa0" },
- { "tosgeax", -1, 0, -1, "tosgea0" },
- { "tosgtax", -1, 0, -1, "tosgta0" },
- { "tosleax", -1, 0, -1, "toslea0" },
- { "tosorax", -1, 0, -1, "tosora0" },
- { "ldaxidx", -1, -1, 1, "ldaxi" },
- { "ldeaxysp", -1, -1, 3, "ldeax0sp" },
- { "lsubeqysp", -1, -1, 0, "lsubeq0sp" },
- { "steaxysp", -1, -1, 0, "steax0sp" },
- { "subeqysp", -1, -1, 0, "subeq0sp" },
- { "tosaslax", -1, 0, -1, "tosasla0" },
- { "tosasrax", -1, 0, -1, "tosasra0" },
- { "tosltax", -1, 0, -1, "toslta0" },
- { "tosmodax", -1, 0, -1, "tosmoda0" },
- { "tosmulax", -1, 0, -1, "tosmula0" },
- { "tosneax", -1, 0, -1, "tosnea0" },
- { "tosrsubax", -1, 0, -1, "tosrsuba0" },
- { "tosshlax", -1, 0, -1, "tosshla0" },
- { "tosshrax", -1, 0, -1, "tosshra0" },
- { "tossubax", -1, 0, -1, "tossuba0" },
- { "tosudivax", -1, 0, -1, "tosudiva0" },
- { "tosugeax", -1, 0, -1, "tosugea0" },
- { "tosugtax", -1, 0, -1, "tosugta0" },
- { "tosuleax", -1, 0, -1, "tosulea0" },
- { "tosultax", -1, 0, -1, "tosulta0" },
- { "tosumodax", -1, 0, -1, "tosumoda0" },
- { "tosumulax", -1, 0, -1, "tosumula0" },
- { "tosxorax", -1, 0, -1, "tosxora0" },
- { "zzzzzzzz", -1, -1, -1, "zzzzzzzz" },
-
-#if 0
- "tosadd0ax", /* tosaddeax, sreg = 0 */
- "laddeqa", /* laddeq, sreg = 0, x = 0 */
- "laddeq1", /* laddeq, sreg = 0, x = 0, a = 1 */
- "tosand0ax", /* tosandeax, sreg = 0 */
- "tosdiv0ax", /* tosdiveax, sreg = 0 */
- "tosmod0ax", /* tosmodeax, sreg = 0 */
- "tosmul0ax", /* tosmuleax, sreg = 0 */
- "tosumul0ax", /* tosumuleax, sreg = 0 */
- "tosor0ax", /* tosoreax, sreg = 0 */
- "push0ax", /* pusheax, sreg = 0 */
- "tosrsub0ax", /* tosrsubeax, sreg = 0 */
- "tosshl0ax", /* tosshleax, sreg = 0 */
- "tosasl0ax", /* tosasleax, sreg = 0 */
- "tosshr0ax", /* tosshreax, sreg = 0 */
- "tosasr0ax", /* tosasreax, sreg = 0 */
- "tossub0ax", /* tossubeax, sreg = 0 */
- "lsubeqa", /* lsubeq, sreg = 0, x = 0 */
- "lsubeq1", /* lsubeq, sreg = 0, x = 0, a = 1 */
- "tosudiv0ax", /* tosudiveax, sreg = 0 */
- "tosumod0ax", /* tosumodeax, sreg = 0 */
- "tosxor0ax", /* tosxoreax, sreg = 0 */
-#endif
+ /* Name A register X register Y register flags replacement */
+ {
+ "addeqysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "addeq0sp"
+ },{
+ "laddeq",
+ {
+ /* A X Y SRegLo */
+ 1, 0, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "laddeq1"
+ },{
+ "laddeq",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "laddeqa"
+ },{
+ "laddeqysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "laddeq0sp"
+ },{
+ "ldaxidx",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 1, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "ldaxi"
+ },{
+ "ldaxysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 1, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "ldax0sp"
+ },{
+ "ldeaxidx",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 3, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "ldeaxi"
+ },{
+ "ldeaxysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 3, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "ldeax0sp"
+ },{
+ "leaaxsp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "leaa0sp"
+ },{
+ "lsubeq",
+ {
+ /* A X Y SRegLo */
+ 1, 0, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "lsubeq1"
+ },{
+ "lsubeq",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "lsubeqa"
+ },{
+ "lsubeqysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "lsubeq0sp"
+ },{
+ "pusha",
+ {
+ /* A X Y SRegLo */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "pushc0"
+ },{
+ "pusha",
+ {
+ /* A X Y SRegLo */
+ 1, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "pushc1"
+ },{
+ "pusha",
+ {
+ /* A X Y SRegLo */
+ 2, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "pushc2"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "push0"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 1, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "push1"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 2, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "push2"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 3, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "push3"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 4, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "push4"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 5, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "push5"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 6, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "push6"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ 7, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "push7"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "pusha0"
+ },{
+ "pushax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0xFF, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_SLOWER,
+ "pushaFF"
+ },{
+ "pushaysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "pusha0sp"
+ },{
+ "pusheax",
+ {
+ /* A X Y SRegLo */
+ 0, 0, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "pushl0"
+ },{
+ "pusheax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "push0ax"
+ },{
+ "pushwidx",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 1, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "pushw"
+ },{
+ "pushwysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 3, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "pushw0sp"
+ },{
+ "staxysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "stax0sp"
+ },{
+ "steaxysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "steax0sp"
+ },{
+ "subeqysp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "subeq0sp"
+ },{
+ "tosaddax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosadda0"
+ },{
+ "tosaddeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosadd0ax"
+ },{
+ "tosandax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosanda0"
+ },{
+ "tosandeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosand0ax"
+ },{
+ "tosdivax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosdiva0"
+ },{
+ "tosdiveax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosdiv0ax"
+ },{
+ "toseqax",
+ {
+ /* A X Y SRegLo */
+ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "toseq00"
+ },{
+ "toseqax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "toseqa0"
+ },{
+ "tosgeax",
+ {
+ /* A X Y SRegLo */
+ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosge00"
+ },{
+ "tosgeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosgea0"
+ },{
+ "tosgtax",
+ {
+ /* A X Y SRegLo */
+ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosgt00"
+ },{
+ "tosgtax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosgta0"
+ },{
+ "tosicmp",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosicmp0"
+ },{
+ "tosleax",
+ {
+ /* A X Y SRegLo */
+ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosle00"
+ },{
+ "tosleax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "toslea0"
+ },{
+ "tosltax",
+ {
+ /* A X Y SRegLo */
+ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "toslt00"
+ },{
+ "tosltax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "toslta0"
+ },{
+ "tosmodax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosmoda0"
+ },{
+ "tosmodeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosmod0ax"
+ },{
+ "tosmulax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosmula0"
+ },{
+ "tosmuleax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosmul0ax"
+ },{
+ "tosneax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosnea0"
+ },{
+ "tosorax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosora0"
+ },{
+ "tosoreax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosor0ax"
+ },{
+ "tosrsubax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosrsuba0"
+ },{
+ "tosrsubeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosrsub0ax"
+ },{
+ "tossubax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tossuba0"
+ },{
+ "tossubeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tossub0ax"
+ },{
+ "tosudivax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosudiva0"
+ },{
+ "tosudiveax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosudiv0ax"
+ },{
+ "tosugeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosugea0"
+ },{
+ "tosugtax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosugta0"
+ },{
+ "tosuleax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosulea0"
+ },{
+ "tosultax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosulta0"
+ },{
+ "tosumodax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosumoda0"
+ },{
+ "tosumodeax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosumod0ax"
+ },{
+ "tosumulax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosumula0"
+ },{
+ "tosumuleax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosumul0ax"
+ },{
+ "tosxorax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosxora0"
+ },{
+ "tosxoreax",
+ {
+ /* A X Y SRegLo */
+ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0,
+ /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */
+ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL
+ },
+ F_NONE,
+ "tosxor0ax"
+ },
+
};
#define CALL_COUNT (sizeof(CallTable) / sizeof(CallTable[0]))
/*****************************************************************************/
-/* Helpers */
+/* Helpers */
/*****************************************************************************/
static const CallDesc* FindCall (const char* Name)
/* Find the function with the given name. Return a pointer to the table entry
- * or NULL if the function was not found.
- */
+** or NULL if the function was not found.
+*/
{
/* Do a binary search */
int First = 0;
- int Last = (sizeof(CallTable) / sizeof(CallTable[0])) - 1;
- int Current;
- int Result;
+ int Last = CALL_COUNT - 1;
int Found = 0;
while (First <= Last) {
- /* Set current to mid of range */
- Current = (Last + First) / 2;
-
- /* Do a compare */
- Result = strcmp (CallTable[Current].LongFunc, Name);
- if (Result < 0) {
- First = Current + 1;
- } else {
- Last = Current - 1;
- if (Result == 0) {
- /* Found. Repeat the procedure until the first of all entries
- * with the same name is found.
- */
- Found = 1;
- }
- }
+ /* Set current to mid of range */
+ int Current = (Last + First) / 2;
+ /* Do a compare */
+ int Result = strcmp (CallTable[Current].LongFunc, Name);
+ if (Result < 0) {
+ First = Current + 1;
+ } else {
+ Last = Current - 1;
+ if (Result == 0) {
+ /* Found. Repeat the procedure until the first of all entries
+ ** with the same name is found.
+ */
+ Found = 1;
+ }
+ }
}
/* Return the first entry if found, or NULL otherwise */
+static int RegMatch (short Expected, short Actual)
+/* Check for a register match. If Expected has a value, it must be identical
+** to Actual.
+*/
+{
+ return RegValIsUnknown (Expected) || (Expected == Actual);
+}
+
+
+
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
unsigned OptSize1 (CodeSeg* S)
/* Do size optimization by calling special subroutines that preload registers.
- * This routine does not work standalone, it needs a following register load
- * removal pass.
- */
+** This routine does not work standalone, it needs a following register load
+** removal pass.
+*/
{
CodeEntry* E;
unsigned Changes = 0;
unsigned I;
- /* Generate register info for the following step */
- CS_GenRegInfo (S);
+ /* Are we optimizing for size */
+ int OptForSize = (S->CodeSizeFactor < 100);
/* Walk over the entries */
I = 0;
while (I < CS_GetEntryCount (S)) {
- /* Get next entry */
- E = CS_GetEntry (S, I);
+ const CallDesc* D;
+
+ /* Get next entry */
+ E = CS_GetEntry (S, I);
+
+ /* Check if it's a subroutine call */
+ if (E->OPC == OP65_JSR && (D = FindCall (E->Arg)) != 0) {
+
+ /* Get input register info for this insn */
+ const RegContents* In = &E->RI->In;
+
+ /* FindCall finds the first entry that matches our function name.
+ ** The names are listed in "best match" order, so search for the
+ ** first one, that fulfills our conditions.
+ */
+ while (1) {
- /* Check if it's a subroutine call */
- if (E->OPC == OP65_JSR) {
+ /* Check the registers and allow slower code only if
+ ** optimizing for size.
+ */
+ if ((OptForSize || (D->Flags & F_SLOWER) == 0) &&
+ RegMatch (D->Regs.RegA, In->RegA) &&
+ RegMatch (D->Regs.RegX, In->RegX) &&
+ RegMatch (D->Regs.RegY, In->RegY) &&
+ RegMatch (D->Regs.SRegLo, In->SRegLo) &&
+ RegMatch (D->Regs.SRegHi, In->SRegHi)) {
- /* Check for any of the known functions. */
- const CallDesc* D = FindCall (E->Arg);
- while (D && strcmp (D->LongFunc, E->Arg) == 0) {
- /* Check the registers */
- if ((D->A < 0 || D->A == E->RI->In.RegA) &&
- (D->X < 0 || D->X == E->RI->In.RegX) &&
- (D->Y < 0 || D->Y == E->RI->In.RegY)) {
- /* Ok, match for all registers */
+ /* Ok, match for all conditions */
CodeEntry* X;
X = NewCodeEntry (E->OPC, E->AM, D->ShortFunc, 0, E->LI);
CS_InsertEntry (S, X, I+1);
/* Remember that we had changes */
++Changes;
+
+ /* Done */
+ break;
+ }
+
+ /* Next table entry, bail out if next entry not valid */
+ if (++D >= CallTable + CALL_COUNT ||
+ strcmp (D->LongFunc, E->Arg) != 0) {
+ /* End of table or entries reached */
+ break;
}
- ++D;
}
}
- /* Next entry */
- ++I;
+ /* Next entry */
+ ++I;
}
- /* Free register info */
- CS_FreeRegInfo (S);
-
/* Return the number of changes made */
return Changes;
}
unsigned OptSize2 (CodeSeg* S)
/* Do size optimization by using shorter code sequences, even if this
- * introduces relations between instructions. This step must be one of the
- * last steps, because it makes further work much more difficult.
- */
+** introduces relations between instructions. This step must be one of the
+** last steps, because it makes further work much more difficult.
+*/
{
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)) {
+ /* Get next entry */
+ CodeEntry* E = CS_GetEntry (S, I);
- /* Get next entry */
- CodeEntry* E = CS_GetEntry (S, I);
-
- /* Assume we have no replacement */
- CodeEntry* X = 0;
-
- /* Check the instruction */
- switch (E->OPC) {
-
- case OP65_LDA:
- if (CE_KnownImm (E)) {
- short Val = (short) E->Num;
- if (Val == E->RI->In.RegX) {
- X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI);
- } else if (Val == E->RI->In.RegY) {
- X = NewCodeEntry (OP65_TYA, AM65_IMP, 0, 0, E->LI);
- } else if (E->RI->In.RegA >= 0 && CPU >= CPU_65C02) {
- if (Val == ((E->RI->In.RegA - 1) & 0xFF)) {
- X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI);
- } else if (Val == ((E->RI->In.RegA + 1) & 0xFF)) {
- X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
- }
- }
- }
- break;
-
- case OP65_LDX:
- if (CE_KnownImm (E)) {
- short Val = (short) E->Num;
- if (E->RI->In.RegX >= 0 && Val == ((E->RI->In.RegX - 1) & 0xFF)) {
- X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI);
- } else if (E->RI->In.RegX >= 0 && Val == ((E->RI->In.RegX + 1) & 0xFF)) {
- X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
- } else if (Val == E->RI->In.RegA) {
- X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
+ /* Get the input registers */
+ const RegContents* In = &E->RI->In;
+
+ /* Assume we have no replacement */
+ CodeEntry* X = 0;
+
+ /* Check the instruction */
+ switch (E->OPC) {
+
+ case OP65_LDA:
+ if (CE_IsConstImm (E)) {
+ short Val = (short) E->Num;
+ if (Val == In->RegX) {
+ X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI);
+ } else if (Val == In->RegY) {
+ X = NewCodeEntry (OP65_TYA, AM65_IMP, 0, 0, E->LI);
+ } else if (RegValIsKnown (In->RegA) && (CPUIsets[CPU] & CPU_ISET_65SC02) != 0) {
+ if (Val == ((In->RegA - 1) & 0xFF)) {
+ X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI);
+ } else if (Val == ((In->RegA + 1) & 0xFF)) {
+ X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
+ }
}
- }
- break;
-
- case OP65_LDY:
- if (CE_KnownImm (E)) {
- short Val = (short) E->Num;
- if (E->RI->In.RegY >= 0 && Val == ((E->RI->In.RegY - 1) & 0xFF)) {
- X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
- } else if (E->RI->In.RegY >= 0 && Val == ((E->RI->In.RegY + 1) & 0xFF)) {
- X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI);
- } else if (Val == E->RI->In.RegA) {
- X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI);
- }
- }
- break;
-
- default:
- /* Avoid gcc warnings */
- break;
-
- }
-
- /* Insert the replacement if we have one */
- if (X) {
- CS_InsertEntry (S, X, I+1);
- CS_DelEntry (S, I);
- ++Changes;
- }
-
- /* Next entry */
- ++I;
+ }
+ break;
- }
+ case OP65_LDX:
+ if (CE_IsConstImm (E)) {
+ short Val = (short) E->Num;
+ if (RegValIsKnown (In->RegX) && Val == ((In->RegX - 1) & 0xFF)) {
+ X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI);
+ } else if (RegValIsKnown (In->RegX) && Val == ((In->RegX + 1) & 0xFF)) {
+ X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
+ } else if (Val == In->RegA) {
+ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
+ }
+ }
+ break;
- /* Free register info */
- CS_FreeRegInfo (S);
+ case OP65_LDY:
+ if (CE_IsConstImm (E)) {
+ short Val = (short) E->Num;
+ if (RegValIsKnown (In->RegY) && Val == ((In->RegY - 1) & 0xFF)) {
+ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
+ } else if (RegValIsKnown (In->RegY) && Val == ((In->RegY + 1) & 0xFF)) {
+ X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI);
+ } else if (Val == In->RegA) {
+ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI);
+ }
+ }
+ break;
- /* Return the number of changes made */
- return Changes;
-}
+ default:
+ /* Avoid gcc warnings */
+ break;
+
+ }
+
+ /* Insert the replacement if we have one */
+ if (X) {
+ CS_InsertEntry (S, X, I+1);
+ CS_DelEntry (S, I);
+ ++Changes;
+ }
+ /* Next entry */
+ ++I;
+ }
+ /* Return the number of changes made */
+ return Changes;
+}