diff --git a/src/cc65/asmcode.c b/src/cc65/asmcode.c
index 046043f2b..b139af1c8 100644
--- a/src/cc65/asmcode.c
+++ b/src/cc65/asmcode.c
@@ -63,7 +63,7 @@ void AddCodeHint (const char* Hint)
 CodeMark GetCodePos (void)
 /* Get a marker pointing to the current output position */
 {
-    return GetCodeSegEntries (CS->Code);
+    return GetCodeEntryCount (CS->Code);
 }
 
 
@@ -83,7 +83,7 @@ void WriteOutput (FILE* F)
     SymEntry* Entry;
 
     /* Output the global data segment */
-    CHECK (GetCodeSegEntries (CS->Code) == 0);
+    CHECK (GetCodeEntryCount (CS->Code) == 0);
     OutputSegments (CS, F);
 
     /* Output all global or referenced functions */
diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c
index d8f852bc9..f2661e1e5 100644
--- a/src/cc65/codeent.c
+++ b/src/cc65/codeent.c
@@ -33,6 +33,8 @@
 
 
 
+#include <string.h>
+
 /* common */
 #include "check.h"
 #include "xmalloc.h"
@@ -53,6 +55,41 @@
 
 
 
+/* Empty argument */
+static char EmptyArg[] = "";
+
+
+
+/*****************************************************************************/
+/*			       Helper functions				     */
+/*****************************************************************************/
+
+
+
+static void FreeArg (char* Arg)
+/* Free a code entry argument */
+{
+    if (Arg != EmptyArg) {
+	xfree (Arg);
+    }
+}
+
+
+
+static char* GetArgCopy (const char* Arg)
+/* Create an argument copy for assignment */
+{
+    if (Arg && Arg[0] != '\0') {
+	/* Create a copy */
+	return xstrdup (Arg);
+    } else {
+	/* Use the empty argument string */
+	return EmptyArg;
+    }
+}
+
+
+
 /*****************************************************************************/
 /*     	       	      	   	     Code				     */
 /*****************************************************************************/
@@ -70,17 +107,17 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel*
     E->AM   	= AM;
     E->Size 	= GetInsnSize (E->OPC, E->AM);
     E->Hints	= 0;
-    E->Arg  	= (Arg && Arg[0] != '\0')? xstrdup (Arg) : 0;
+    E->Arg     	= GetArgCopy (Arg);
     E->Num  	= 0;
     E->Flags	= 0;
     E->Info	= D->Info;
     E->Use	= D->Use;
     E->Chg	= D->Chg;
-    if (E->OPC == OPC_JSR && E->Arg) {
-	/* A subroutine call */
+    if (E->OPC == OPC_JSR) {
+     	/* A subroutine call */
      	GetFuncInfo (E->Arg, &E->Use, &E->Chg);
     } else {
-	/* Some other instruction */
+     	/* Some other instruction */
      	E->Use |= GetAMUseInfo (AM);
     }
     E->JumpTo	= JumpTo;
@@ -88,7 +125,7 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel*
 
     /* If we have a label given, add this entry to the label */
     if (JumpTo) {
-	CollAppend (&JumpTo->JumpFrom, E);
+     	CollAppend (&JumpTo->JumpFrom, E);
     }
 
     /* Return the initialized struct */
@@ -101,7 +138,7 @@ void FreeCodeEntry (CodeEntry* E)
 /* Free the given code entry */
 {
     /* Free the string argument if we have one */
-    xfree (E->Arg);
+    FreeArg (E->Arg);
 
     /* Cleanup the collection */
     DoneCollection (&E->Labels);
@@ -112,6 +149,29 @@ void FreeCodeEntry (CodeEntry* E)
 
 
 
+int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2)
+/* Check if both code entries are equal */
+{
+    return E1->OPC == E2->OPC && E1->AM == E2->AM && strcmp (E1->Arg, E2->Arg) == 0;
+}
+
+
+
+void AttachCodeLabel (CodeEntry* E, CodeLabel* L)
+/* Attach the label to the entry */
+{
+    /* Mark the label as defined */
+    L->Flags |= LF_DEF;
+
+    /* Add it to the entries label list */
+    CollAppend (&E->Labels, L);
+
+    /* Tell the label about it's owner */
+    L->Owner = E;
+}
+
+
+
 int CodeEntryHasLabel (const CodeEntry* E)
 /* Check if the given code entry has labels attached */
 {
@@ -120,6 +180,35 @@ int CodeEntryHasLabel (const CodeEntry* E)
 
 
 
+unsigned GetCodeLabelCount (const CodeEntry* E)
+/* Get the number of labels attached to this entry */
+{
+    return CollCount (&E->Labels);
+}
+
+
+
+CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index)
+/* Get a label from this code entry */
+{
+    return CollAt (&E->Labels, Index);
+}
+
+
+
+void MoveCodeLabel (CodeLabel* L, CodeEntry* E)
+/* Move the code label L from it's former owner to the code entry E. */
+{
+    /* Delete the label from the owner */
+    CollDeleteItem (&L->Owner->Labels, L);
+
+    /* Set the new owner */
+    CollAppend (&E->Labels, L);
+    L->Owner = E;
+}
+
+
+
 int CodeEntryHasMark (const CodeEntry* E)
 /* Return true if the given code entry has the CEF_USERMARK flag set */
 {
@@ -144,23 +233,14 @@ void CodeEntryResetMark (CodeEntry* E)
 
 
 
-CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index)
-/* Get a label from this code entry */
+void CodeEntrySetArg (CodeEntry* E, const char* Arg)
+/* Set a new argument for the given code entry. An old string is deleted. */
 {
-    return CollAt (&E->Labels, Index);
-}
+    /* Free the old argument */
+    FreeArg (E->Arg);
 
-
-
-void MoveCodeLabel (CodeLabel* L, CodeEntry* E)
-/* Move the code label L from it's former owner to the code entry E. */
-{
-    /* Delete the label from the owner */
-    CollDeleteItem (&L->Owner->Labels, L);
-
-    /* Set the new owner */
-    CollAppend (&E->Labels, L);
-    L->Owner = E;
+    /* Assign the new one */
+    E->Arg = GetArgCopy (Arg);
 }
 
 
@@ -170,6 +250,7 @@ void OutputCodeEntry (const CodeEntry* E, FILE* F)
 {
     const OPCDesc* D;
     unsigned Chars;
+    const char* Target;
 
     /* If we have a label, print that */
     unsigned LabelCount = CollCount (&E->Labels);
@@ -235,8 +316,8 @@ void OutputCodeEntry (const CodeEntry* E, FILE* F)
 
 	case AM_BRA:
 	    /* branch */
-	    CHECK (E->JumpTo != 0);
-	    Chars += fprintf (F, "%*s%s", 9-Chars, "", E->JumpTo->Name);
+	    Target = E->JumpTo? E->JumpTo->Name : E->Arg;
+	    Chars += fprintf (F, "%*s%s", 9-Chars, "", Target);
 	    break;
 
 	default:
diff --git a/src/cc65/codeent.h b/src/cc65/codeent.h
index ab0790989..ba704eb28 100644
--- a/src/cc65/codeent.h
+++ b/src/cc65/codeent.h
@@ -90,9 +90,24 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel*
 void FreeCodeEntry (CodeEntry* E);
 /* Free the given code entry */
 
+int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2);
+/* Check if both code entries are equal */
+
+void AttachCodeLabel (CodeEntry* E, CodeLabel* L);
+/* Attach the label to the entry */
+
 int CodeEntryHasLabel (const CodeEntry* E);
 /* Check if the given code entry has labels attached */
 
+unsigned GetCodeLabelCount (const CodeEntry* E);
+/* Get the number of labels attached to this entry */
+
+CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index);
+/* Get a label from this code entry */
+
+void MoveCodeLabel (CodeLabel* L, CodeEntry* E);
+/* Move the code label L from it's former owner to the code entry E. */
+
 int CodeEntryHasMark (const CodeEntry* E);
 /* Return true if the given code entry has the CEF_USERMARK flag set */
 
@@ -102,11 +117,8 @@ void CodeEntrySetMark (CodeEntry* E);
 void CodeEntryResetMark (CodeEntry* E);
 /* Reset the CEF_USERMARK flag for the given entry */
 
-CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index);
-/* Get a label from this code entry */
-
-void MoveCodeLabel (CodeLabel* L, CodeEntry* E);
-/* Move the code label L from it's former owner to the code entry E. */
+void CodeEntrySetArg (CodeEntry* E, const char* Arg);
+/* Set a new argument for the given code entry. An old string is deleted. */
 
 void OutputCodeEntry (const CodeEntry* E, FILE* F);
 /* Output the code entry to a file */
diff --git a/src/cc65/codelab.c b/src/cc65/codelab.c
index 97ed7e3b8..89b45b0e6 100644
--- a/src/cc65/codelab.c
+++ b/src/cc65/codelab.c
@@ -96,18 +96,6 @@ void AddLabelRef (CodeLabel* L, struct CodeEntry* E)
 
 
 
-unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E)
-/* Remove a reference to this label, return the number of remaining references */
-{
-    /* Delete the item */
-    CollDeleteItem (&L->JumpFrom, E);
-
-    /* Return the number of remaining references */
-    return CollCount (&L->JumpFrom);
-}
-
-
-
 void MoveLabelRefs (CodeLabel* OldLabel, CodeLabel* NewLabel)
 /* Move all references to OldLabel to point to NewLabel. OldLabel will have no
  * more references on return.
diff --git a/src/cc65/codelab.h b/src/cc65/codelab.h
index 0aef14857..bd24fc5d5 100644
--- a/src/cc65/codelab.h
+++ b/src/cc65/codelab.h
@@ -92,9 +92,6 @@ void FreeCodeLabel (CodeLabel* L);
 void AddLabelRef (CodeLabel* L, struct CodeEntry* E);
 /* Let the CodeEntry E reference the label L */
 
-unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E);
-/* Remove a reference to this label, return the number of remaining references */
-
 void MoveLabelRefs (CodeLabel* OldLabel, CodeLabel* NewLabel);
 /* Move all references to OldLabel to point to NewLabel. OldLabel will have no
  * more references on return.
diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c
index 241934187..90417a537 100644
--- a/src/cc65/codeopt.c
+++ b/src/cc65/codeopt.c
@@ -37,6 +37,7 @@
 #include "print.h"
 
 /* cc65 */
+#include "asmlabel.h"
 #include "codeent.h"
 #include "codeinfo.h"
 #include "global.h"
@@ -70,7 +71,7 @@ static void OptDeadJumps (CodeSeg* S)
     unsigned I;
 
     /* Get the number of entries, bail out if we have less than two entries */
-    unsigned Count = CollCount (&S->Entries);
+    unsigned Count = GetCodeEntryCount (S);
     if (Count < 2) {
      	return;
     }
@@ -121,7 +122,7 @@ static void OptDeadCode (CodeSeg* S)
     unsigned I;
 
     /* Get the number of entries, bail out if we have less than two entries */
-    unsigned Count = CollCount (&S->Entries);
+    unsigned Count = GetCodeEntryCount (S);
     if (Count < 2) {
      	return;
     }
@@ -175,7 +176,7 @@ static void OptJumpCascades (CodeSeg* S)
     unsigned I;
 
     /* Get the number of entries, bail out if we have no entries */
-    unsigned Count = CollCount (&S->Entries);
+    unsigned Count = GetCodeEntryCount (S);
     if (Count == 0) {
      	return;
     }
@@ -184,45 +185,72 @@ static void OptJumpCascades (CodeSeg* S)
     I = 0;
     while (I < Count) {
 
-	CodeLabel* OldLabel;
-	CodeLabel* NewLabel;
-
 	/* Get this entry */
 	CodeEntry* E = GetCodeEntry (S, I);
 
-       	/* Check if it's a branch, if it has a label attached, and if the
-	 * instruction at this label is also a branch, and (important) if
-	 * both instructions are not identical.
+       	/* Check if it's a branch, if it has a jump label, and if this jump
+	 * label is not attached to the instruction itself.
 	 */
-       	if (E->AM == AM_BRA    	       	 		&&	/* It's a branch */
-	    (OldLabel = E->JumpTo) != 0 		&&	/* Label attached */
-       	    OldLabel->Owner->AM == AM_BRA 		&&	/* Jumps to a branch.. */
-	    (NewLabel = OldLabel->Owner->JumpTo) != 0	&&	/* ..which has a label */
-	    OldLabel->Owner != E) {				/* And both are distinct */
+     	if ((E->Info & OF_BRA) != 0 && E->JumpTo != 0 && E->JumpTo->Owner != E) {
 
-	    /* Get the instruction that has the new label attached */
-	    CodeEntry* N = OldLabel->Owner;
+     	    /* Get the label this insn is branching to */
+     	    CodeLabel* OldLabel = E->JumpTo;
 
-	    /* Remove the reference to our label and delete it if this was
-	     * the last reference.
+     	    /* Get the entry we're branching to */
+     	    CodeEntry* N = OldLabel->Owner;
+
+	    /* If the entry we're branching to is not itself a branch, it is
+	     * not what we're searching for.
 	     */
-	    if (RemoveLabelRef (OldLabel, E) == 0) {
-		/* Delete it */
-		DelCodeLabel (S, OldLabel);
+	    if ((N->Info & OF_BRA) == 0) {
+	       	goto NextEntry;
 	    }
 
-	    /* Use the usage information from the new instruction */
-	    E->Use = N->Use;
-	    E->Chg = N->Chg;
+	    /* Check if we can use the final target label. This is the case,
+	     * if the target branch is an absolut branch, or if it is a
+	     * conditional branch checking the same condition as the first one.
+	     */
+	    if ((N->Info & OF_UBRA) != 0 ||
+       	       	((E->Info & OF_CBRA) != 0 &&
+		 GetBranchCond (E->OPC)  == GetBranchCond (N->OPC))) {
 
-	    /* Use the new label */
-	    AddLabelRef (NewLabel, E);
+	     	/* This is a jump cascade and we may jump to the final target.
+	     	 * If we have a label, move the reference to this label. If
+	     	 * we don't have a label, use the argument instead.
+	     	 */
+	     	if (N->JumpTo) {
+	     	    /* Move the reference to the new insn */
+	     	    MoveCodeLabelRef (S, E, N->JumpTo);
+	     	} else {
+		    /* Remove the reference to the old label */
+		    RemoveCodeLabelRef (S, E);
+		}
 
-	    /* Remember ,we had changes */
-	    ++OptChanges;
+	     	/* Use the new argument */
+	     	CodeEntrySetArg (E, N->Arg);
+
+	     	/* Use the usage information from the new instruction */
+	     	E->Use = N->Use;
+	     	E->Chg = N->Chg;
+
+	     	/* Remember, we had changes */
+	     	++OptChanges;
+
+	     	/* Done */
+	      	goto NextEntry;
+
+	    }
+
+	    /* Check if both are conditional branches, and the condition of
+	     * the second is the inverse of that of the first. In this case,
+	     * the second branch will never be taken, and we may jump directly
+	     * to the instruction behind this one.
+	     */
+	    goto NextEntry;
 
 	}
 
+NextEntry:
 	/* Next entry */
 	++I;
 
@@ -232,7 +260,7 @@ static void OptJumpCascades (CodeSeg* S)
 
 
 /*****************************************************************************/
-/*			       Optimize jsr/rts				     */
+/*	     	    	       Optimize jsr/rts				     */
 /*****************************************************************************/
 
 
@@ -246,7 +274,7 @@ static void OptRTS (CodeSeg* S)
     unsigned I;
 
     /* Get the number of entries, bail out if we have less than 2 entries */
-    unsigned Count = CollCount (&S->Entries);
+    unsigned Count = GetCodeEntryCount (S);
     if (Count < 2) {
      	return;
     }
@@ -261,12 +289,11 @@ static void OptRTS (CodeSeg* S)
 	/* Check if it's a subroutine call and if the following insn is RTS */
 	if (E->OPC == OPC_JSR && GetCodeEntry(S,I+1)->OPC == OPC_RTS) {
 
-	    /* Change the jsr to a jmp */
-	    E->OPC = OPC_JMP;
-
-	    /* Change the opcode info to that of the jump */
+	    /* Change the jsr to a jmp and use the additional info for a jump */
+	    E->OPC  = OPC_JMP;
+	    E->AM   = AM_BRA;
 	    E->Info = GetOPCInfo (OPC_JMP);
-					   
+
        	    /* Remember, we had changes */
 	    ++OptChanges;
 
@@ -293,29 +320,76 @@ static void OptJumpTarget (CodeSeg* S)
  * the branch gets removed.
  */
 {
+    CodeEntry* E1;	/* Entry 1 */
+    CodeEntry* E2;	/* Entry 2 */
+    CodeEntry* T1;	/* Jump target entry 1 */
+    CodeEntry* T2;	/* Jump target entry 2 */
+    CodeLabel* TL1;	/* Target label 1 */
+    unsigned TI;	/* Target index */
     unsigned I;
 
     /* Get the number of entries, bail out if we have not enough */
-    unsigned Count = CollCount (&S->Entries);
+    unsigned Count = GetCodeEntryCount (S);
     if (Count < 3) {
      	return;
     }
 
-    /* Walk over all entries minus the first one */
-    I = 1;
-    while (I < Count) {
+    /* Walk over the entries */
+    I = 0;
+    while (I < Count-1) {
 
-	/* Get this entry and the entry before this one */
-	CodeEntry* E = GetCodeEntry (S, I);
+      	/* Get next entry */
+       	E2 = GetCodeEntry (S, I+1);
 
 	/* Check if we have a jump or branch, and a matching label */
-	if ((E->Info & OF_UBRA) != 0 && E->JumpTo) {
+       	if ((E2->Info & OF_UBRA) != 0 && E2->JumpTo) {
+
+	    /* Get the target instruction for the label */
+	    T2 = E2->JumpTo->Owner;
+
+	    /* Get the entry preceeding this one (if possible) */
+	    TI = GetCodeEntryIndex (S, T2);
+	    if (TI == 0) {
+	       	/* There is no entry before this one */
+	       	goto NextEntry;
+	    }
+	    T1 = GetCodeEntry (S, TI-1);
+
+	    /* Get the entry preceeding the jump */
+	    E1 = GetCodeEntry (S, I);
+
+	    /* Check if both preceeding instructions are identical */
+	    if (!CodeEntriesAreEqual (E1, T1)) {
+	    	/* Not equal, try next */
+	    	goto NextEntry;
+	    }
+
+	    /* Get the label for the instruction preceeding the jump target.
+	     * This routine will create a new label if the instruction does
+	     * not already have one.
+	     */
+      	    TL1 = GenCodeLabel (S, T1);
+
+	    /* Change the jump target to point to this new label */
+	    MoveCodeLabelRef (S, E2, TL1);
+
+	    /* If the instruction preceeding the jump has labels attached,
+	     * move references to this label to the new label.
+	     */
+	    if (CodeEntryHasLabel (E1)) {
+		MoveCodeLabels (S, E1, T1);
+	    }
+
+	    /* Remove the entry preceeding the jump */
+	    DelCodeEntry (S, I);
+	    --Count;
 
        	    /* Remember, we had changes */
 	    ++OptChanges;
 
 	}
 
+NextEntry:
 	/* Next entry */
 	++I;
 
@@ -325,7 +399,7 @@ static void OptJumpTarget (CodeSeg* S)
 
 
 /*****************************************************************************/
-/*     	       	      	  	     Code				     */
+/*     	       	      	  	     Code	   			     */
 /*****************************************************************************/
 
 
@@ -341,6 +415,7 @@ void RunOpt (CodeSeg* S)
        	OptDeadJumps,  	 	/* Remove dead jumps */
 	OptDeadCode,	 	/* Remove dead code */
 	OptRTS,			/* Change jsr/rts to jmp */
+	OptJumpTarget,		/* Optimize jump targets */
     };
 
     /* Repeat all steps until there are no more changes */
diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c
index 5c54b2231..62642e0bf 100644
--- a/src/cc65/codeseg.c
+++ b/src/cc65/codeseg.c
@@ -45,6 +45,7 @@
 #include "xsprintf.h"
 
 /* cc65 */
+#include "asmlabel.h"
 #include "codeent.h"
 #include "codeinfo.h"
 #include "error.h"
@@ -61,7 +62,7 @@
 static void MoveLabelsToPool (CodeSeg* S, CodeEntry* E)
 /* Move the labels of the code entry E to the label pool of the code segment */
 {
-    unsigned LabelCount = CollCount (&E->Labels);
+    unsigned LabelCount = GetCodeLabelCount (E);
     while (LabelCount--) {
 	CodeLabel* L = GetCodeLabel (E, LabelCount);
 	L->Flags &= ~LF_DEF;
@@ -405,14 +406,12 @@ void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
 	unsigned I;
 	unsigned LabelCount = CollCount (&S->Labels);
 	for (I = 0; I < LabelCount; ++I) {
+
 	    /* Get the label */
 	    CodeLabel* L = CollAt (&S->Labels, I);
-	    /* Mark it as defined */
-	    L->Flags |= LF_DEF;
-	    /* Move it to the code entry */
-	    CollAppend (&E->Labels, L);
-	    /* Tell the label about it's owner */
-	    L->Owner = E;
+
+	    /* Attach it to the entry */
+	    AttachCodeLabel (E, L);
 	}
 
 	/* Delete the transfered labels */
@@ -441,13 +440,13 @@ void DelCodeEntry (CodeSeg* S, unsigned Index)
      * insn may already have a label. In that case change all reference to
      * this label and delete the label instead of moving it.
      */
-    unsigned Count = CollCount (&E->Labels);
+    unsigned Count = GetCodeLabelCount (E);
     if (Count > 0) {
 
 	/* The instruction has labels attached. Check if there is a next
 	 * instruction.
 	 */
-	if (Index == GetCodeSegEntries (S)-1) {
+	if (Index == GetCodeEntryCount (S)-1) {
 
 	    /* No next instruction, move to the codeseg label pool */
 	    MoveLabelsToPool (S, E);
@@ -457,35 +456,9 @@ void DelCodeEntry (CodeSeg* S, unsigned Index)
 	    /* There is a next insn, get it */
 	    CodeEntry* N = GetCodeEntry (S, Index+1);
 
-	    /* Does this next insn have itself a label? */
-	    if (CodeEntryHasLabel (N)) {
+	    /* Move labels to the next entry */
+	    MoveCodeLabels (S, E, N);
 
-		/* The next insn does already have a label - move references */
-		CodeLabel* NewLabel = GetCodeLabel (N, 0);
-		while (Count--) {
-
-		    /* Get the next label */
-		    CodeLabel* L = GetCodeLabel (E, Count);
-
-		    /* Move references */
-		    MoveLabelRefs (L, NewLabel);
-
-		    /* Delete the label */
-		    DelCodeLabel (S, L);
-
-		}
-
-	    } else {
-
-		/* The next insn does not have a label, just move them */
-	    	while (Count--) {
-
-		    /* Move the label to the new entry */
-		    MoveCodeLabel (GetCodeLabel (E, Count), N);
-
-		}
-
-	    }
 	}
     }
 
@@ -493,15 +466,8 @@ void DelCodeEntry (CodeSeg* S, unsigned Index)
      * the reference count for this label drops to zero, remove this label.
      */
     if (E->JumpTo) {
-
        	/* Remove the reference */
-       	if (RemoveLabelRef (E->JumpTo, E) == 0) {
-	    /* No references remaining, remove the label */
-	    DelCodeLabel (S, E->JumpTo);
-	}
-
-	/* Reset the label pointer to avoid problems later */
-	E->JumpTo = 0;
+       	RemoveCodeLabelRef (S, E);
     }
 
     /* Delete the pointer to the insn */
@@ -521,6 +487,16 @@ struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index)
 
 
 
+unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E)
+/* Return the index of a code entry */
+{
+    int Index = CollIndex (&S->Entries, E);
+    CHECK (Index >= 0);
+    return Index;
+}
+
+
+
 void AddCodeLabel (CodeSeg* S, const char* Name)
 /* Add a code label for the next instruction to follow */
 {
@@ -545,6 +521,40 @@ void AddCodeLabel (CodeSeg* S, const char* Name)
 
 
 
+CodeLabel* GenCodeLabel (CodeSeg* S, struct CodeEntry* E)
+/* If the code entry E does already have a label, return it. Otherwise
+ * create a new label, attach it to E and return it.
+ */
+{
+    CodeLabel* L;
+
+    if (CodeEntryHasLabel (E)) {
+
+	/* Get the label from this entry */
+	L = GetCodeLabel (E, 0);
+
+    } else {
+
+	/* Get a new name */
+	const char* Name = LocalLabelName (GetLocalLabel ());
+
+	/* Generate the hash over the name */
+	unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE;
+
+	/* Create a new label */
+	L = NewCodeSegLabel (S, Name, Hash);
+
+	/* Attach this label to the code entry */
+	AttachCodeLabel (E, L);
+
+    }
+
+    /* Return the label */
+    return L;
+}
+
+
+
 void DelCodeLabel (CodeSeg* S, CodeLabel* L)
 /* Remove references from this label and delete it. */
 {
@@ -588,93 +598,15 @@ void DelCodeLabel (CodeSeg* S, CodeLabel* L)
 
 
 
-void AddCodeSegHint (CodeSeg* S, unsigned Hint)
-/* Add a hint for the preceeding instruction */
-{
-    CodeEntry* E;
-
-    /* Get the number of entries in this segment */
-    unsigned EntryCount = CollCount (&S->Entries);
-
-    /* Must have at least one entry */
-    CHECK (EntryCount > 0);
-
-    /* Get the last entry */
-    E = GetCodeEntry (S, EntryCount-1);
-
-    /* Add the hint */
-    E->Hints |= Hint;
-}
-
-
-
-void DelCodeSegAfter (CodeSeg* S, unsigned Last)
-/* Delete all entries including the given one */
-{
-    /* Get the number of entries in this segment */
-    unsigned Count = CollCount (&S->Entries);
-
-    /* Remove all entries after the given one */
-    while (Last < Count) {
-
-	/* Get the next entry */
-	CodeEntry* E = GetCodeEntry (S, Count-1);
-
-	/* We have to transfer all labels to the code segment label pool */
-	MoveLabelsToPool (S, E);
-
-	/* Remove the code entry */
-      	FreeCodeEntry (E);
-      	CollDelete (&S->Entries, Count-1);
-      	--Count;
-    }
-}
-
-
-
-void OutputCodeSeg (const CodeSeg* S, FILE* F)
-/* Output the code segment data to a file */
-{
-    unsigned I;
-
-    /* Get the number of entries in this segment */
-    unsigned Count = CollCount (&S->Entries);
-
-    /* If the code segment is empty, bail out here */
-    if (Count == 0) {
-	return;
-    }
-
-    /* Output the segment directive */
-    fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
-
-    /* If this is a segment for a function, enter a function */
-    if (S->Func) {
-	fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
-    }
-
-    /* Output all entries */
-    for (I = 0; I < Count; ++I) {
-	OutputCodeEntry (CollConstAt (&S->Entries, I), F);
-    }
-
-    /* If this is a segment for a function, leave the function */
-    if (S->Func) {
-	fprintf (F, "\n.endproc\n\n");
-    }
-}
-
-
-
 void MergeCodeLabels (CodeSeg* S)
 /* Merge code labels. That means: For each instruction, remove all labels but
- * one and adjust the code entries accordingly.
+ * one and adjust references accordingly.
  */
 {
     unsigned I;
 
     /* Walk over all code entries */
-    unsigned EntryCount = CollCount (&S->Entries);
+    unsigned EntryCount = GetCodeEntryCount (S);
     for (I = 0; I < EntryCount; ++I) {
 
        	CodeLabel* RefLab;
@@ -684,7 +616,7 @@ void MergeCodeLabels (CodeSeg* S)
 	CodeEntry* E = GetCodeEntry (S, I);
 
     	/* If this entry has zero labels, continue with the next one */
-    	unsigned LabelCount = CollCount (&E->Labels);
+    	unsigned LabelCount = GetCodeLabelCount (E);
     	if (LabelCount == 0) {
     	    continue;
     	}
@@ -722,7 +654,174 @@ void MergeCodeLabels (CodeSeg* S)
 
 
 
-unsigned GetCodeSegEntries (const CodeSeg* S)
+void MoveCodeLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New)
+/* Move all labels from Old to New. The routine will move the labels itself
+ * if New does not have any labels, and move references if there is at least
+ * a label for new. If references are moved, the old label is deleted
+ * afterwards.
+ */
+{
+    /* Get the number of labels to move */
+    unsigned OldLabelCount = GetCodeLabelCount (Old);
+
+    /* Does the new entry have itself a label? */
+    if (CodeEntryHasLabel (New)) {
+
+	/* The new entry does already have a label - move references */
+	CodeLabel* NewLabel = GetCodeLabel (New, 0);
+	while (OldLabelCount--) {
+
+	    /* Get the next label */
+	    CodeLabel* OldLabel = GetCodeLabel (Old, OldLabelCount);
+
+	    /* Move references */
+	    MoveLabelRefs (OldLabel, NewLabel);
+
+	    /* Delete the label */
+	    DelCodeLabel (S, OldLabel);
+
+	}
+
+    } else {
+
+	/* The new entry does not have a label, just move them */
+	while (OldLabelCount--) {
+
+	    /* Move the label to the new entry */
+	    MoveCodeLabel (GetCodeLabel (Old, OldLabelCount), New);
+
+	}
+
+    }
+}
+
+
+
+void RemoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E)			  
+/* Remove the reference between E and the label it jumps to. The reference
+ * will be removed on both sides and E->JumpTo will be 0 after that. If
+ * the reference was the only one for the label, the label will get
+ * deleted.
+ */
+{
+    /* Get a pointer to the label and make sure it exists */
+    CodeLabel* L = E->JumpTo;
+    CHECK (L != 0);
+
+    /* Delete the entry from the label */
+    CollDeleteItem (&L->JumpFrom, E);
+
+    /* The entry jumps no longer to L */
+    E->JumpTo = 0;
+
+    /* If there are no more references, delete the label */
+    if (CollCount (&L->JumpFrom) == 0) {
+	DelCodeLabel (S, L);
+    }
+}
+
+
+
+void MoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L)
+/* Change the reference of E to L instead of the current one. If this
+ * was the only reference to the old label, the old label will get
+ * deleted.
+ */
+{
+    /* Get the old label */
+    CodeLabel* OldLabel = E->JumpTo;
+
+    /* Be sure that code entry references a label */
+    PRECONDITION (OldLabel != 0);
+
+    /* Remove the reference to our label */
+    RemoveCodeLabelRef (S, E);
+
+    /* Use the new label */
+    AddLabelRef (L, E);
+}
+
+
+
+void AddCodeSegHint (CodeSeg* S, unsigned Hint)
+/* Add a hint for the preceeding instruction */
+{
+    CodeEntry* E;
+
+    /* Get the number of entries in this segment */
+    unsigned EntryCount = GetCodeEntryCount (S);
+
+    /* Must have at least one entry */
+    CHECK (EntryCount > 0);
+
+    /* Get the last entry */
+    E = GetCodeEntry (S, EntryCount-1);
+
+    /* Add the hint */
+    E->Hints |= Hint;
+}
+
+
+
+void DelCodeSegAfter (CodeSeg* S, unsigned Last)
+/* Delete all entries including the given one */
+{
+    /* Get the number of entries in this segment */
+    unsigned Count = GetCodeEntryCount (S);
+
+    /* Remove all entries after the given one */
+    while (Last < Count) {
+
+	/* Get the next entry */
+	CodeEntry* E = GetCodeEntry (S, Count-1);
+
+	/* We have to transfer all labels to the code segment label pool */
+	MoveLabelsToPool (S, E);
+
+	/* Remove the code entry */
+      	FreeCodeEntry (E);
+      	CollDelete (&S->Entries, Count-1);
+      	--Count;
+    }
+}
+
+
+
+void OutputCodeSeg (const CodeSeg* S, FILE* F)
+/* Output the code segment data to a file */
+{
+    unsigned I;
+
+    /* Get the number of entries in this segment */
+    unsigned Count = GetCodeEntryCount (S);
+
+    /* If the code segment is empty, bail out here */
+    if (Count == 0) {
+	return;
+    }
+
+    /* Output the segment directive */
+    fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
+
+    /* If this is a segment for a function, enter a function */
+    if (S->Func) {
+	fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
+    }
+
+    /* Output all entries */
+    for (I = 0; I < Count; ++I) {
+	OutputCodeEntry (CollConstAt (&S->Entries, I), F);
+    }
+
+    /* If this is a segment for a function, leave the function */
+    if (S->Func) {
+	fprintf (F, "\n.endproc\n\n");
+    }
+}
+
+
+
+unsigned GetCodeEntryCount (const CodeSeg* S)
 /* Return the number of entries for the given code segment */
 {
     return CollCount (&S->Entries);
diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h
index e7a2fdaf1..a90e31b1a 100644
--- a/src/cc65/codeseg.h
+++ b/src/cc65/codeseg.h
@@ -103,12 +103,45 @@ void DelCodeEntry (CodeSeg* S, unsigned Index);
 struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index);
 /* Get an entry from the given code segment */
 
+unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E);
+/* Return the index of a code entry */
+
 void AddCodeLabel (CodeSeg* S, const char* Name);
 /* Add a code label for the next instruction to follow */
 
+CodeLabel* GenCodeLabel (CodeSeg* S, struct CodeEntry* E);
+/* If the code entry E does already have a label, return it. Otherwise
+ * create a new label, attach it to E and return it.
+ */
+
 void DelCodeLabel (CodeSeg* S, CodeLabel* L);
 /* Remove references from this label and delete it. */
 
+void MergeCodeLabels (CodeSeg* S);
+/* Merge code labels. That means: For each instruction, remove all labels but
+ * one and adjust references accordingly.
+ */
+
+void MoveCodeLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New);
+/* Move all labels from Old to New. The routine will move the labels itself
+ * if New does not have any labels, and move references if there is at least
+ * a label for new. If references are moved, the old label is deleted
+ * afterwards.
+ */
+
+void RemoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E);
+/* Remove the reference between E and the label it jumps to. The reference
+ * will be removed on both sides and E->JumpTo will be 0 after that. If
+ * the reference was the only one for the label, the label will get
+ * deleted.
+ */
+
+void MoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L);
+/* Change the reference of E to L instead of the current one. If this
+ * was the only reference to the old label, the old label will get
+ * deleted.
+ */
+
 void AddCodeSegHint (CodeSeg* S, unsigned Hint);
 /* Add a hint for the preceeding instruction */
 
@@ -118,12 +151,7 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last);
 void OutputCodeSeg (const CodeSeg* S, FILE* F);
 /* Output the code segment data to a file */
 
-void MergeCodeLabels (CodeSeg* S);
-/* Merge code labels. That means: For each instruction, remove all labels but
- * one and adjust the code entries accordingly.
- */
-
-unsigned GetCodeSegEntries (const CodeSeg* S);
+unsigned GetCodeEntryCount (const CodeSeg* S);
 /* Return the number of entries for the given code segment */
 
 
diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c
index 11888de9c..79f6658f5 100644
--- a/src/cc65/opcodes.c
+++ b/src/cc65/opcodes.c
@@ -42,6 +42,7 @@
 
 /* cc65 */
 #include "codeinfo.h"
+#include "cpu.h"
 #include "error.h"
 #include "opcodes.h"
 
@@ -265,7 +266,147 @@ opc_t GetInverseBranch (opc_t OPC)
        	case OPC_JPL:  	return OPC_JMI;
        	case OPC_JVC:  	return OPC_JVS;
        	case OPC_JVS:  	return OPC_JVC;
-	default:	Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
+	default:  	Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
+    }
+}
+
+
+
+opc_t MakeShortBranch (opc_t OPC)
+/* Return the short version of the given branch. If the branch is already
+ * a short branch, return the opcode unchanged.
+ */
+{
+    switch (OPC) {
+       	case OPC_BCC:
+       	case OPC_JCC:  	return OPC_BCC;
+       	case OPC_BCS:
+       	case OPC_JCS:  	return OPC_BCS;
+       	case OPC_BEQ:
+       	case OPC_JEQ:  	return OPC_BEQ;
+       	case OPC_BMI:
+       	case OPC_JMI:  	return OPC_BMI;
+       	case OPC_BNE:
+       	case OPC_JNE:  	return OPC_BNE;
+       	case OPC_BPL:
+       	case OPC_JPL:  	return OPC_BPL;
+       	case OPC_BVC:
+       	case OPC_JVC:  	return OPC_BVC;
+       	case OPC_BVS:
+       	case OPC_JVS:  	return OPC_BVS;
+       	case OPC_BRA:
+	case OPC_JMP:	return (CPU == CPU_65C02)? OPC_BRA : OPC_JMP;
+       	default:       	Internal ("GetShortBranch: Invalid opcode: %d", OPC);
+    }
+}
+
+
+
+opc_t MakeLongBranch (opc_t OPC)
+/* Return the long version of the given branch. If the branch is already
+ * a long branch, return the opcode unchanged.
+ */
+{
+    switch (OPC) {
+       	case OPC_BCC:
+       	case OPC_JCC:  	return OPC_JCC;
+       	case OPC_BCS:
+       	case OPC_JCS:  	return OPC_JCS;
+       	case OPC_BEQ:
+       	case OPC_JEQ:  	return OPC_JEQ;
+       	case OPC_BMI:
+       	case OPC_JMI:  	return OPC_JMI;
+       	case OPC_BNE:
+       	case OPC_JNE:  	return OPC_JNE;
+       	case OPC_BPL:
+       	case OPC_JPL:  	return OPC_JPL;
+       	case OPC_BVC:
+       	case OPC_JVC:  	return OPC_JVC;
+       	case OPC_BVS:
+       	case OPC_JVS:  	return OPC_JVS;
+	case OPC_BRA:
+	case OPC_JMP:	return OPC_JMP;
+       	default:       	Internal ("GetShortBranch: Invalid opcode: %d", OPC);
+    }
+}
+
+
+
+bc_t GetBranchCond (opc_t OPC)
+/* Get the condition for the conditional branch in OPC */
+{
+    switch (OPC) {
+       	case OPC_BCC:  	return BC_CC;
+       	case OPC_BCS:  	return BC_CS;
+       	case OPC_BEQ:  	return BC_EQ;
+       	case OPC_BMI:  	return BC_MI;
+       	case OPC_BNE:  	return BC_NE;
+       	case OPC_BPL:  	return BC_PL;
+       	case OPC_BVC:  	return BC_VC;
+       	case OPC_BVS:  	return BC_VS;
+       	case OPC_JCC:  	return BC_CC;
+       	case OPC_JCS:  	return BC_CS;
+       	case OPC_JEQ:  	return BC_EQ;
+       	case OPC_JMI:  	return BC_MI;
+       	case OPC_JNE:  	return BC_NE;
+       	case OPC_JPL:  	return BC_PL;
+       	case OPC_JVC:  	return BC_VC;
+       	case OPC_JVS:  	return BC_VS;
+	default:  	Internal ("GetBranchCond: Invalid opcode: %d", OPC);
+    }
+}
+
+
+
+bc_t GetInverseCond (bc_t BC)
+/* Return the inverse condition of the given one */
+{
+    switch (BC) {
+       	case BC_CC:  	return BC_CS;
+       	case BC_CS:  	return BC_CC;
+       	case BC_EQ:  	return BC_NE;
+       	case BC_MI:  	return BC_PL;
+       	case BC_NE:  	return BC_EQ;
+       	case BC_PL:  	return BC_MI;
+       	case BC_VC:  	return BC_VS;
+       	case BC_VS:  	return BC_VC;
+	default:  	Internal ("GetInverseCond: Invalid condition: %d", BC);
+    }
+}
+
+
+
+opc_t GetLongBranch (bc_t BC)
+/* Return a long branch for the given branch condition */
+{
+    switch (BC) {
+	case BC_CC:	return OPC_JCC;
+	case BC_CS:	return OPC_JCS;
+	case BC_EQ:	return OPC_JEQ;
+	case BC_MI:	return OPC_JMI;
+	case BC_NE:	return OPC_JNE;
+	case BC_PL:	return OPC_JPL;
+	case BC_VC:	return OPC_JVC;
+	case BC_VS:	return OPC_JVS;
+       	default:       	Internal ("GetLongBranch: Invalid condition: %d", BC);
+    }
+}
+
+
+
+opc_t GetShortBranch (bc_t BC)
+/* Return a short branch for the given branch condition */
+{
+    switch (BC) {
+       	case BC_CC:    	return OPC_BCC;
+       	case BC_CS:    	return OPC_BCS;
+       	case BC_EQ:    	return OPC_BEQ;
+       	case BC_MI:    	return OPC_BMI;
+       	case BC_NE:    	return OPC_BNE;
+       	case BC_PL:    	return OPC_BPL;
+       	case BC_VC:    	return OPC_BVC;
+       	case BC_VS:    	return OPC_BVS;
+       	default:       	Internal ("GetShortBranch: Invalid condition: %d", BC);
     }
 }
 
diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h
index bc827dd1a..df590fd14 100644
--- a/src/cc65/opcodes.h
+++ b/src/cc65/opcodes.h
@@ -138,6 +138,19 @@ typedef enum {
     AM_BRA     	= 0x0800       		/* branch */
 } am_t;
 
+/* Branch conditions */
+typedef enum {
+    BC_CC,
+    BC_CS,
+    BC_EQ,
+    BC_MI,
+    BC_NE,
+    BC_PL,
+    BC_SR,
+    BC_VC,
+    BC_VS
+} bc_t;
+
 /* Opcode info */
 #define OF_NONE	0x0000U	       		/* No additional information */
 #define OF_UBRA	0x0001U	       		/* Unconditional branch */
@@ -186,6 +199,28 @@ unsigned char GetAMUseInfo (am_t AM);
 opc_t GetInverseBranch (opc_t OPC);
 /* Return a branch that reverse the condition of the branch given in OPC */
 
+opc_t MakeShortBranch (opc_t OPC);
+/* Return the short version of the given branch. If the branch is already
+ * a short branch, return the opcode unchanged.
+ */
+
+opc_t MakeLongBranch (opc_t OPC);
+/* Return the long version of the given branch. If the branch is already
+ * a long branch, return the opcode unchanged.
+ */
+
+bc_t GetBranchCond (opc_t OPC);
+/* Get the condition for the conditional branch in OPC */
+
+bc_t GetInverseCond (bc_t BC);
+/* Return the inverse condition of the given one */
+
+opc_t GetLongBranch (bc_t BC);
+/* Return a long branch for the given branch condition */
+
+opc_t GetShortBranch (bc_t BC);
+/* Return a short branch for the given branch condition */
+
 
 
 /* End of opcodes.h */