+/*****************************************************************************/
+/* Remove dead code */
+/*****************************************************************************/
+
+
+
+static void OptDeadCode (CodeSeg* S)
+/* Remove dead code (code that follows an unconditional jump or an rts/rti
+ * and has no label)
+ */
+{
+ unsigned I;
+
+ /* Get the number of entries, bail out if we have less than two entries */
+ unsigned Count = CollCount (&S->Entries);
+ if (Count < 2) {
+ return;
+ }
+
+ /* Walk over all entries minus the last one */
+ I = 0;
+ while (I < Count-1) {
+
+ /* Get this entry */
+ CodeEntry* E = CollAt (&S->Entries, I);
+
+ /* Check if it's an unconditional branch, and if the next entry has
+ * no labels attached
+ */
+ if ((E->OPC == OPC_JMP || E->OPC == OPC_BRA || E->OPC == OPC_RTS || E->OPC == OPC_RTI) &&
+ !CodeEntryHasLabel (CollAt (&S->Entries, I+1))) {
+
+ /* Delete the next entry */
+ DelCodeSegLine (S, I+1);
+
+ /* Keep the number of entries updated */
+ --Count;
+
+ /* Remember, we had changes */
+ ++OptChanges;
+
+ } else {
+
+ /* Next entry */
+ ++I;
+
+ }
+ }
+}
+
+
+
+/*****************************************************************************/
+/* Optimize jump cascades */
+/*****************************************************************************/
+
+
+
+static void OptJumpCascades (CodeSeg* S)
+/* Optimize jump cascades (jumps to jumps). In such a case, the jump is
+ * replaced by a jump to the final location. This will in some cases produce
+ * worse code, because some jump targets are no longer reachable by short
+ * branches, but this is quite rare, so there are more advantages than
+ * disadvantages.
+ */
+{
+ unsigned I;
+
+ /* Get the number of entries, bail out if we have no entries */
+ unsigned Count = CollCount (&S->Entries);
+ if (Count == 0) {
+ return;
+ }
+
+ /* Walk over all entries */
+ I = 0;
+ while (I < Count) {
+
+ CodeLabel* OldLabel;
+ CodeLabel* NewLabel;
+
+ /* Get this entry */
+ CodeEntry* E = CollAt (&S->Entries, I);
+
+ /* Check if it's a branch, if it has a label attached, and if the
+ * instruction at this label is also a branch.
+ */
+ if (E->AM == AM_BRA &&
+ (OldLabel = E->JumpTo) != 0 &&
+ OldLabel->Owner->AM == AM_BRA &&
+ (NewLabel = OldLabel->Owner->JumpTo) != 0) {
+
+ /* Get the instruction that has the new label attached */
+ CodeEntry* N = OldLabel->Owner;
+
+ /* Remove the reference to our label and delete it if this was
+ * the last reference.
+ */
+ if (RemoveLabelRef (OldLabel, E) == 0) {
+ /* Delete it */
+ DelCodeLabel (S, OldLabel);
+ }
+
+ /* Remove usage information from the entry and use the usage
+ * information from the new instruction instead.
+ */
+ E->Info &= ~(CI_MASK_USE | CI_MASK_CHG);
+ E->Info |= N->Info & ~(CI_MASK_USE | CI_MASK_CHG);
+
+ /* Use the new label */
+ AddLabelRef (NewLabel, E);
+
+ /* Remember ,we had changes */
+ ++OptChanges;
+
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+}
+
+
+