private void mergeCodeUnits(Program fromPgm, AddressSetView addrSet, boolean copyBytes,
			TaskMonitor monitor) throws MemoryAccessException, CancelledException {
		if (addrSet.isEmpty()) {
			return;
		}
		adjustCodeUnitPicked(fromPgm, addrSet);

		Listing resultListing = resultPgm.getListing();

		ProgramContext originContext = fromPgm.getProgramContext();
		ProgramContext resultContext = resultPgm.getProgramContext();
		Register contextReg = originContext.getBaseContextRegister();

		for (AddressRange range : addrSet) {

			// Clear any existing code units in the merged program
			// where this code unit needs to go.
			// May cause the merge code unit to lose info attached to it, such as references.
			resultListing.clearCodeUnits(range.getMinAddress(), range.getMaxAddress(), false);

			if (contextReg != Register.NO_CONTEXT) {
				// Copy context register value
				mergeProgramContext(resultContext, originContext,
					originContext.getBaseContextRegister(), range, monitor);
			}
		}

		CodeUnitIterator sourceCodeUnits = fromPgm.getListing().getCodeUnits(addrSet, true);
		long totalAddresses = addrSet.getNumAddresses();
		long granularity = (totalAddresses / 100) + 1;
		int mergeProgress = 0;
		int mergeCount = 0;
		monitor.initialize(totalAddresses);
		// Get each code unit out of the iterator and set it in the merged
		// program if it is an instruction.
		while (sourceCodeUnits.hasNext()) {
			monitor.checkCancelled();
			CodeUnit cu = sourceCodeUnits.next();
			if (mergeCount > granularity) {
				monitor.setProgress(mergeProgress);
				incrementProgress(1);
				mergeCount = 0;
			}
			//monitor.setMessage("Replacing Code Unit @ " + cu.getMinAddress().toString());
			try {
				// create a new instruction or data.
				if (cu instanceof Instruction) {
					performMergeInstruction((Instruction) cu, true);
				}
				else if (cu instanceof Data) {
					performMergeData((Data) cu, copyBytes);
				}
			}
			catch (CodeUnitInsertionException exc) {
			}
			int increment =
				(int) (cu.getMaxAddress().getOffset() - cu.getMinAddress().getOffset() + 1);
			mergeProgress += increment;
			mergeCount += increment;
		}
	}
Merges all the current conflicts according to the conflictOption.
@param listingPanel the listing merge panel
@param chosenConflictOption the conflict option to use when merging (should be ASK_USER for interactive).
@param monitor the status monitor
@throws CancelledException if the user cancels
@throws MemoryAccessException if bytes can't be merged.
Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/CodeUnitMerger.java