/* */
/* */
/* */
-/* (C) 2001-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2001-2009, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
CMP_ULE, CMP_ULT, CMP_UGE, CMP_UGT
};
-/* Table to show which compares are signed (use the N flag) */
-static const char CmpSignedTab [] = {
- 0, 0, 1, 1, 1, 1, 0, 0, 0, 0
-};
-
/*****************************************************************************/
strcmp (L[1]->Arg, "tmp1") == 0 &&
L[2]->OPC == OP65_ORA &&
strcmp (L[2]->Arg, "tmp1") == 0) {
-
+
CodeEntry* X;
/* Insert the ora instead */
-unsigned OptCmp2 (CodeSeg* S)
+unsigned OptCmp2 (CodeSeg* S)
/* Search for the sequence
*
* stx xx
!CS_RangeHasLabel (S, I+1, 2) &&
CS_GetEntries (S, L+1, I+1, 2) &&
L[1]->OPC == OP65_CMP &&
- CE_KnownImm (L[1]) &&
- L[1]->Num == 0) {
+ CE_IsKnownImm (L[1], 0)) {
+
+ int Delete = 0;
/* Check for the call to boolxx. We only remove the compare if
* the carry flag is evaluated later, because the load will not
* set the carry flag.
*/
if (L[2]->OPC == OP65_JSR) {
- switch (FindBoolCmpCond (L[2]->Arg)) {
-
- case CMP_EQ:
- case CMP_NE:
- case CMP_GT:
- case CMP_GE:
- case CMP_LT:
- case CMP_LE:
- /* Remove the compare */
- CS_DelEntry (S, I+1);
- ++Changes;
- break;
-
- case CMP_UGT:
+ switch (FindBoolCmpCond (L[2]->Arg)) {
+
+ case CMP_EQ:
+ case CMP_NE:
+ case CMP_GT:
+ case CMP_GE:
+ case CMP_LT:
+ case CMP_LE:
+ /* Remove the compare */
+ Delete = 1;
+ break;
+
+ case CMP_UGT:
case CMP_UGE:
- case CMP_ULT:
- case CMP_ULE:
- case CMP_INV:
- /* Leave it alone */
- break;
- }
-
- } else {
-
- /* Check for a branch on conditions that are set by the load.
- * Beware: The insn may branch to another conditional branch
- * that evaluates other flags, so check that.
- */
- CodeEntry* E = L[2];
- int Delete = 0;
- while (1) {
- if ((E->Info & (OF_CBRA|OF_UBRA)) != 0) {
- /* A conditional branch. Check if it jumps on a
- * condition not set by the load.
- */
- if ((E->Info & (OF_FBRA|OF_UBRA)) == 0) {
- /* Invalid branch */
- break;
- } else if (E->JumpTo == 0) {
- /* Jump to external */
- Delete = 1;
- break;
- } else {
- /* Check target of branch */
- E = E->JumpTo->Owner;
- }
- } else {
- /* Some other insn */
- Delete = 1;
- break;
- }
- }
-
- /* Delete the compare if we can */
- if (Delete) {
- CS_DelEntry (S, I+1);
- ++Changes;
- }
- }
+ case CMP_ULT:
+ case CMP_ULE:
+ case CMP_INV:
+ /* Leave it alone */
+ break;
+ }
+
+ } else if ((L[2]->Info & OF_FBRA) != 0) {
+
+ /* The following insn branches on the condition of a load, so
+ * the compare instruction can be removed.
+ */
+ Delete = 1;
+
+ }
+
+ /* Delete the compare if we can */
+ if (Delete) {
+ CS_DelEntry (S, I+1);
+ ++Changes;
+ }
}
/* Next entry */
/* Check for the sequence */
if (L[0]->OPC == OP65_LDY &&
- CE_KnownImm (L[0]) &&
+ CE_IsConstImm (L[0]) &&
CS_GetEntries (S, L+1, I+1, 5) &&
!CE_HasLabel (L[1]) &&
CE_IsCallTo (L[1], "ldaxysp") &&
/* Check for a compare against an immediate value */
if ((E->Info & OF_CMP) != 0 &&
(RegVal = GetCmpRegVal (E)) >= 0 &&
- CE_KnownImm (E)) {
+ CE_IsConstImm (E)) {
/* We are able to evaluate the compare at compile time. Check if
* one or more branches are ahead.
+unsigned OptCmp9 (CodeSeg* S)
+/* Search for the sequence
+ *
+ * sbc xx
+ * bvs/bvc L
+ * eor #$80
+ * L: asl a
+ * bcc/bcs somewhere
+ *
+ * If A is not used later (which should be the case), we can branch on the N
+ * flag instead of the carry flag and remove the asl.
+ */
+{
+ unsigned Changes = 0;
+ unsigned I;
+
+ /* Walk over the entries */
+ I = 0;
+ while (I < CS_GetEntryCount (S)) {
+
+ CodeEntry* L[5];
+
+ /* Get next entry */
+ L[0] = CS_GetEntry (S, I);
+
+ /* Check for the sequence */
+ if (L[0]->OPC == OP65_SBC &&
+ CS_GetEntries (S, L+1, I+1, 4) &&
+ (L[1]->OPC == OP65_BVC ||
+ L[1]->OPC == OP65_BVS) &&
+ L[1]->JumpTo != 0 &&
+ L[1]->JumpTo->Owner == L[3] &&
+ L[2]->OPC == OP65_EOR &&
+ CE_IsKnownImm (L[2], 0x80) &&
+ L[3]->OPC == OP65_ASL &&
+ L[3]->AM == AM65_ACC &&
+ (L[4]->OPC == OP65_BCC ||
+ L[4]->OPC == OP65_BCS ||
+ L[4]->OPC == OP65_JCC ||
+ L[4]->OPC == OP65_JCS) &&
+ !CE_HasLabel (L[4]) &&
+ !RegAUsed (S, I+4)) {
+
+ /* Replace the branch condition */
+ switch (GetBranchCond (L[4]->OPC)) {
+ case BC_CC: CE_ReplaceOPC (L[4], OP65_JPL); break;
+ case BC_CS: CE_ReplaceOPC (L[4], OP65_JMI); break;
+ default: Internal ("Unknown branch condition in OptCmp9");
+ }
+
+ /* Delete the asl insn */
+ CS_DelEntry (S, I+3);
+
+ /* Next sequence is somewhat ahead (if any) */
+ I += 3;
+
+ /* Remember, we had changes */
+ ++Changes;
+ }
+
+ /* Next entry */
+ ++I;
+ }
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+