*/
{
static char Buf[16];
- xsprintf (Buf, sizeof (Buf), "$%02X", (char) Num);
+ xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned char) Num);
return Buf;
}
+int CE_UseLoadFlags (const CodeEntry* E)
+/* Return true if the instruction uses any flags that are set by a load of
+ * a register (N and Z).
+ */
+{
+ /* A branch will use the flags */
+ if (E->Info & OF_FBRA) {
+ return 1;
+ }
+
+ /* Call of a boolean transformer routine will also use the flags */
+ if (E->OPC == OP65_JSR) {
+ /* Get the condition that is evaluated and check it */
+ switch (FindBoolCmpCond (E->Arg)) {
+ case CMP_EQ:
+ case CMP_NE:
+ case CMP_GT:
+ case CMP_GE:
+ case CMP_LT:
+ case CMP_LE:
+ case CMP_UGT:
+ case CMP_ULE:
+ case CMP_INV:
+ /* Will use the N or Z flags */
+ return 1;
+
+
+ case CMP_UGE: /* Uses only carry */
+ case CMP_ULT: /* Dito */
+ default: /* No bool transformer subroutine */
+ return 0;
+ }
+ }
+
+ /* Anything else */
+ return 0;
+}
+
+
+
void CE_FreeRegInfo (CodeEntry* E)
/* Free an existing register info struct */
{
# define CE_IsCall(E, Name) ((E)->OPC == OP65_JSR && strcmp ((E)->Arg, (Name)) == 0)
#endif
+int CE_UseLoadFlags (const CodeEntry* E);
+/* Return true if the instruction uses any flags that are set by a load of
+ * a register (N and Z).
+ */
+
void CE_FreeRegInfo (CodeEntry* E);
/* Free an existing register info struct */
+/* Table with the compare suffixes */
+static const char CmpSuffixTab [][4] = {
+ "eq", "ne", "gt", "ge", "lt", "le", "ugt", "uge", "ult", "ule"
+};
+
/* Table listing the function names and code info values for known internally
* used functions. This table should get auto-generated in the future.
*/
+static cmp_t FindCmpCond (const char* Code, unsigned CodeLen)
+/* Search for a compare condition by the given code using the given length */
+{
+ unsigned I;
+
+ /* Linear search */
+ for (I = 0; I < sizeof (CmpSuffixTab) / sizeof (CmpSuffixTab [0]); ++I) {
+ if (strncmp (Code, CmpSuffixTab [I], CodeLen) == 0) {
+ /* Found */
+ return I;
+ }
+ }
+
+ /* Not found */
+ return CMP_INV;
+}
+
+
+
+cmp_t FindBoolCmpCond (const char* Name)
+/* Check if the given string is the name of one of the boolean transformer
+ * subroutine, and if so, return the condition that is evaluated by this
+ * routine. Return CMP_INV if the condition is not recognised.
+ */
+{
+ /* Check for the correct subroutine name */
+ if (strncmp (Name, "bool", 4) == 0) {
+ /* Name is ok, search for the code in the table */
+ return FindCmpCond (Name+4, strlen(Name)-4);
+ } else {
+ /* Not found */
+ return CMP_INV;
+ }
+}
+
+
+
+cmp_t FindTosCmpCond (const char* Name)
+/* Check if this is a call to one of the TOS compare functions (tosgtax).
+ * Return the condition code or CMP_INV on failure.
+ */
+{
+ unsigned Len = strlen (Name);
+
+ /* Check for the correct subroutine name */
+ if (strncmp (Name, "tos", 3) == 0 && strcmp (Name+Len-2, "ax") == 0) {
+ /* Name is ok, search for the code in the table */
+ return FindCmpCond (Name+3, Len-3-2);
+ } else {
+ /* Not found */
+ return CMP_INV;
+ }
+}
+
+
+
+/* Defines for the conditions in a compare */
+typedef enum {
+ CMP_INV = -1,
+ CMP_EQ,
+ CMP_NE,
+ CMP_GT,
+ CMP_GE,
+ CMP_LT,
+ CMP_LE,
+ CMP_UGT,
+ CMP_UGE,
+ CMP_ULT,
+ CMP_ULE
+} cmp_t;
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
* register in question does not have a known value, return REG_NONE.
*/
+cmp_t FindBoolCmpCond (const char* Name);
+/* Check if the given string is the name of one of the boolean transformer
+ * subroutine, and if so, return the condition that is evaluated by this
+ * routine. Return CMP_INV if the condition is not recognised.
+ */
+
+cmp_t FindTosCmpCond (const char* Name);
+/* Check if this is a call to one of the TOS compare functions (tosgtax).
+ * Return the condition code or CMP_INV on failure.
+ */
+
/* End of codeinfo.h */
-/* Defines for the conditions in a compare */
-typedef enum {
- CMP_INV = -1,
- CMP_EQ,
- CMP_NE,
- CMP_GT,
- CMP_GE,
- CMP_LT,
- CMP_LE,
- CMP_UGT,
- CMP_UGE,
- CMP_ULT,
- CMP_ULE
-} cmp_t;
-
-/* Table with the compare suffixes */
-static const char CmpSuffixTab [][4] = {
- "eq", "ne", "gt", "ge", "lt", "le", "ugt", "uge", "ult", "ule"
-};
-
/* Table used to invert a condition, indexed by condition */
static const unsigned char CmpInvertTab [] = {
CMP_NE, CMP_EQ,
-static cmp_t FindCmpCond (const char* Code, unsigned CodeLen)
-/* Search for a compare condition by the given code using the given length */
-{
- unsigned I;
-
- /* Linear search */
- for (I = 0; I < sizeof (CmpSuffixTab) / sizeof (CmpSuffixTab [0]); ++I) {
- if (strncmp (Code, CmpSuffixTab [I], CodeLen) == 0) {
- /* Found */
- return I;
- }
- }
-
- /* Not found */
- return CMP_INV;
-}
-
-
-
-static cmp_t FindBoolCmpCond (const char* Name)
-/* Map a condition suffix to a code. Return the code or CMP_INV on failure */
-{
- /* Check for the correct subroutine name */
- if (strncmp (Name, "bool", 4) == 0) {
- /* Name is ok, search for the code in the table */
- return FindCmpCond (Name+4, strlen(Name)-4);
- } else {
- /* Not found */
- return CMP_INV;
- }
-}
-
-
-
-static cmp_t FindTosCmpCond (const char* Name)
-/* Check if this is a call to one of the TOS compare functions (tosgtax).
- * Return the condition code or CMP_INV on failure.
- */
-{
- unsigned Len = strlen (Name);
-
- /* Check for the correct subroutine name */
- if (strncmp (Name, "tos", 3) == 0 && strcmp (Name+Len-2, "ax") == 0) {
- /* Name is ok, search for the code in the table */
- return FindCmpCond (Name+3, Len-3-2);
- } else {
- /* Not found */
- return CMP_INV;
- }
-}
-
-
-
static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
/* Helper function for the replacement of routines that return a boolean
* followed by a conditional jump. Instead of the boolean value, the condition
/*****************************************************************************/
-/* Remove unused loads and stores */
+/* Remove unused loads and stores */
/*****************************************************************************/
CodeEntry* E = CS_GetEntry (S, I);
/* Check if it's a register load or transfer insn */
- if ((E->Info & (OF_LOAD | OF_XFR | OF_REG_INCDEC)) != 0 &&
- (N = CS_GetNextEntry (S, I)) != 0 &&
- (N->Info & OF_FBRA) == 0) {
+ if ((E->Info & (OF_LOAD | OF_XFR | OF_REG_INCDEC)) != 0 &&
+ (N = CS_GetNextEntry (S, I)) != 0 &&
+ !CE_UseLoadFlags (N)) {
/* Check which sort of load or transfer it is */
unsigned R;
switch (E->OPC) {
- case OP65_DEA:
- case OP65_INA:
- case OP65_LDA:
+ case OP65_DEA:
+ case OP65_INA:
+ case OP65_LDA:
case OP65_TXA:
case OP65_TYA: R = REG_A; break;
- case OP65_DEX:
- case OP65_INX:
- case OP65_LDX:
+ case OP65_DEX:
+ case OP65_INX:
+ case OP65_LDX:
case OP65_TAX: R = REG_X; break;
- case OP65_DEY:
- case OP65_INY:
+ case OP65_DEY:
+ case OP65_INY:
case OP65_LDY:
case OP65_TAY: R = REG_Y; break;
default: goto NextEntry; /* OOPS */
CE_KnownImm (E) && /* Value to be loaded is known */
In->RegA == (long) E->Num && /* Both are equal */
(N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
- (N->Info & OF_FBRA) == 0) { /* Which is not a cond branch */
+ !CE_UseLoadFlags (N)) { /* Which does not use the flags */
Delete = 1;
}
break;
CE_KnownImm (E) && /* Value to be loaded is known */
In->RegX == (long) E->Num && /* Both are equal */
(N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
- (N->Info & OF_FBRA) == 0) { /* Which is not a cond branch */
+ !CE_UseLoadFlags (N)) { /* Which does not use the flags */
Delete = 1;
}
break;
CE_KnownImm (E) && /* Value to be loaded is known */
In->RegY == (long) E->Num && /* Both are equal */
(N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
- (N->Info & OF_FBRA) == 0) { /* Which is not a cond branch */
+ !CE_UseLoadFlags (N)) { /* Which does not use the flags */
Delete = 1;
}
break;
if (In->RegA >= 0 &&
In->RegA == In->RegX &&
(N = CS_GetNextEntry (S, I)) != 0 &&
- (N->Info & OF_FBRA) == 0) {
+ !CE_UseLoadFlags (N)) {
/* Value is identical and not followed by a branch */
Delete = 1;
}
break;
case OP65_TAY:
- if (In->RegA >= 0 &&
- In->RegA == In->RegY &&
+ if (In->RegA >= 0 &&
+ In->RegA == In->RegY &&
(N = CS_GetNextEntry (S, I)) != 0 &&
- (N->Info & OF_FBRA) == 0) {
+ !CE_UseLoadFlags (N)) {
/* Value is identical and not followed by a branch */
Delete = 1;
}
break;
case OP65_TXA:
- if (In->RegX >= 0 &&
- In->RegX == In->RegA &&
+ if (In->RegX >= 0 &&
+ In->RegX == In->RegA &&
(N = CS_GetNextEntry (S, I)) != 0 &&
- (N->Info & OF_FBRA) == 0) {
+ !CE_UseLoadFlags (N)) {
/* Value is identical and not followed by a branch */
Delete = 1;
}
break;
case OP65_TYA:
- if (In->RegY >= 0 &&
- In->RegY == In->RegA &&
+ if (In->RegY >= 0 &&
+ In->RegY == In->RegA &&
(N = CS_GetNextEntry (S, I)) != 0 &&
- (N->Info & OF_FBRA) == 0) {
+ !CE_UseLoadFlags (N)) {
/* Value is identical and not followed by a branch */
Delete = 1;
}
}
- /* Free register info */
+ /* Free register info */
CS_FreeRegInfo (S);
/* Return the number of changes made */
(E->OPC == OP65_STY && N->OPC == OP65_LDY)) &&
strcmp (E->Arg, N->Arg) == 0 &&
(X = CS_GetNextEntry (S, I+1)) != 0 &&
- (X->Info & OF_FBRA) == 0) {
+ !CE_UseLoadFlags (X)) {
/* Register has already the correct value, remove the load */
CS_DelEntry (S, I+1);
*/
if ((X = CS_GetNextEntry (S, I+1)) == 0) {
goto NextEntry;
- }
- if ((X->Info & OF_FBRA) != 0) {
+ }
+ if (CE_UseLoadFlags (X)) {
if (I == 0) {
/* No preceeding entry */
goto NextEntry;
-void DefineData (ExprDesc* lval)
+void DefineData (ExprDesc* Expr)
/* Output a data definition for the given expression */
{
- unsigned flags = lval->Flags;
+ unsigned Flags = Expr->Flags;
- switch (flags & E_MCTYPE) {
+ switch (Flags & E_MCTYPE) {
case E_TCONST:
/* Number */
- g_defdata (TypeOf (lval->Type) | CF_CONST, lval->ConstVal, 0);
+ g_defdata (TypeOf (Expr->Type) | CF_CONST, Expr->ConstVal, 0);
break;
case E_TREGISTER:
case E_TGLAB:
case E_TLLAB:
/* Local or global symbol */
- g_defdata (GlobalModeFlags (flags), lval->Name, lval->ConstVal);
+ g_defdata (GlobalModeFlags (Flags), Expr->Name, Expr->ConstVal);
break;
case E_TLIT:
/* a literal of some kind */
- g_defdata (CF_STATIC, LiteralPoolLabel, lval->ConstVal);
+ g_defdata (CF_STATIC, LiteralPoolLabel, Expr->ConstVal);
break;
default:
- Internal ("Unknown constant type: %04X", flags);
+ Internal ("Unknown constant type: %04X", Flags);
}
}
-static void lconst (unsigned flags, ExprDesc* lval)
-/* Load primary reg with some constant value. */
+static void lconst (unsigned Flags, ExprDesc* Expr)
+/* Load the primary register with some constant value. */
{
- switch (lval->Flags & E_MCTYPE) {
+ switch (Expr->Flags & E_MCTYPE) {
case E_TLOFFS:
- g_leasp (lval->ConstVal);
+ g_leasp (Expr->ConstVal);
break;
case E_TCONST:
/* Number constant */
- g_getimmed (flags | TypeOf (lval->Type) | CF_CONST, lval->ConstVal, 0);
+ g_getimmed (Flags | TypeOf (Expr->Type) | CF_CONST, Expr->ConstVal, 0);
break;
case E_TREGISTER:
case E_TGLAB:
case E_TLLAB:
/* Local or global symbol, load address */
- flags |= GlobalModeFlags (lval->Flags);
- flags &= ~CF_CONST;
- g_getimmed (flags, lval->Name, lval->ConstVal);
+ Flags |= GlobalModeFlags (Expr->Flags);
+ Flags &= ~CF_CONST;
+ g_getimmed (Flags, Expr->Name, Expr->ConstVal);
break;
case E_TLIT:
/* Literal string */
- g_getimmed (CF_STATIC, LiteralPoolLabel, lval->ConstVal);
+ g_getimmed (CF_STATIC, LiteralPoolLabel, Expr->ConstVal);
break;
default:
- Internal ("Unknown constant type: %04X", lval->Flags);
+ Internal ("Unknown constant type: %04X", Expr->Flags);
}
}
-static GenDesc* FindGen (token_t Tok, GenDesc** Table)
+static const GenDesc* FindGen (token_t Tok, const GenDesc** Table)
+/* Find a token in a generator table */
{
- GenDesc* G;
+ const GenDesc* G;
while ((G = *Table) != 0) {
if (G->Tok == Tok) {
return G;
-static int hie_internal (GenDesc** ops, /* List of generators */
+static int hie_internal (const GenDesc** ops, /* List of generators */
ExprDesc* lval, /* parent expr's lval */
int (*hienext) (ExprDesc*),
int* UsedGen) /* next higher level */
ExprDesc lval2;
CodeMark Mark1;
CodeMark Mark2;
- GenDesc* Gen;
+ const GenDesc* Gen;
token_t tok; /* The operator token */
unsigned ltype, type;
int rconst; /* Operand is a constant */
-static int hie_compare (GenDesc** ops, /* List of generators */
- ExprDesc* lval, /* parent expr's lval */
+static int hie_compare (const GenDesc** ops, /* List of generators */
+ ExprDesc* lval, /* parent expr's lval */
int (*hienext) (ExprDesc*))
/* Helper function for the compare operators */
{
ExprDesc lval2;
CodeMark Mark1;
CodeMark Mark2;
- GenDesc* Gen;
+ const GenDesc* Gen;
token_t tok; /* The operator token */
unsigned ltype;
int rconst; /* Operand is a constant */
static int hie9 (ExprDesc *lval)
/* Process * and / operators. */
{
- static GenDesc* hie9_ops [] = {
+ static const GenDesc* hie9_ops [] = {
&GenMUL, &GenDIV, &GenMOD, 0
};
int UsedGen;
static int hie7 (ExprDesc *lval)
/* Parse << and >>. */
{
- static GenDesc* hie7_ops [] = {
+ static const GenDesc* hie7_ops [] = {
&GenASL, &GenASR, 0
};
int UsedGen;
static int hie6 (ExprDesc *lval)
/* process greater-than type comparators */
{
- static GenDesc* hie6_ops [] = {
+ static const GenDesc* hie6_ops [] = {
&GenLT, &GenLE, &GenGE, &GenGT, 0
};
return hie_compare (hie6_ops, lval, hie7);
static int hie5 (ExprDesc *lval)
{
- static GenDesc* hie5_ops[] = {
+ static const GenDesc* hie5_ops[] = {
&GenEQ, &GenNE, 0
};
return hie_compare (hie5_ops, lval, hie6);
static int hie4 (ExprDesc* lval)
/* Handle & (bitwise and) */
{
- static GenDesc* hie4_ops [] = {
+ static const GenDesc* hie4_ops [] = {
&GenAND, 0
};
int UsedGen;
static int hie3 (ExprDesc *lval)
/* Handle ^ (bitwise exclusive or) */
{
- static GenDesc* hie3_ops [] = {
+ static const GenDesc* hie3_ops [] = {
&GenXOR, 0
};
int UsedGen;
static int hie2 (ExprDesc *lval)
/* Handle | (bitwise or) */
{
- static GenDesc* hie2_ops [] = {
+ static const GenDesc* hie2_ops [] = {
&GenOR, 0
};
int UsedGen;
-static void opeq (GenDesc* Gen, ExprDesc *lval, int k)
+static void opeq (const GenDesc* Gen, ExprDesc *lval, int k)
/* Process "op=" operators. */
{
ExprDesc lval2;
-static void addsubeq (GenDesc* Gen, ExprDesc *lval, int k)
+static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
/* Process the += and -= operators */
{
ExprDesc lval2;