public void mergeBytes(final AddressSetView originAddressSet, boolean overwriteInstructions,
			TaskMonitor monitor)
			throws MemoryAccessException, CancelledException, UnsupportedOperationException {
		if (!originToResultTranslator.isOneForOneTranslator()) {
			String message = originToResultTranslator.getClass().getName() +
				" is not a one for one translator and can't merge bytes.";
			throw new UnsupportedOperationException(message);
		}
		AddressSet originByteSet =
			originAddressSet.subtract(ProgramMemoryUtil.getAddressSet(originProgram, false));
		if (originByteSet.isEmpty()) {
			return;
		}

		monitor.setMessage("Finding Instructions...   ");
		AddressSet resultByteSet =
			DiffUtility.getCompatibleAddressSet(originByteSet, resultProgram);
		AddressSet resultInstructionSet = getInstructionSet(resultByteSet, resultListing);

		// Clear the instructions.
		if (overwriteInstructions) {
			monitor.setMessage("Clearing Instructions...   ");
			AddressRangeIterator resultRangeIter = resultInstructionSet.getAddressRanges();
			int count = 0;
			while (resultRangeIter.hasNext()) {
				monitor.checkCancelled();
				AddressRange resultRange = resultRangeIter.next();
				Address resultMin = resultRange.getMinAddress();
				Address resultMax = resultRange.getMaxAddress();
				resultListing.clearCodeUnits(resultMin, resultMax, false, monitor);
				if (count == PROGRESS_COUNTER_GRANULARITY) {
					monitor.setMessage("Clearing Instructions...   " + resultMin.toString(true));
					count = 0;
				}
			}
		}
		else {
			// ignore instruction locations
			AddressSet originInstructionSet =
				DiffUtility.getCompatibleAddressSet(resultInstructionSet, originProgram);
			originByteSet = originByteSet.subtract(originInstructionSet);
			if (originByteSet.isEmpty()) {
				return;
			}
		}

		// Make sure we are only trying to copy bytes to where we have initialized addresses in the result.
		Memory memory = resultProgram.getMemory();
		AddressSetView initializedAddressSet = memory.getLoadedAndInitializedAddressSet();
		AddressSet originInitializedAddressSet =
			DiffUtility.getCompatibleAddressSet(initializedAddressSet, originProgram);
		originByteSet = originByteSet.intersect(originInitializedAddressSet);

		// Get the bytes for each of the address ranges.
		// Overwrite each range's bytes in the merge program.
		monitor.setMessage("Copying Bytes...   ");
		copyBytesInRanges(originByteSet, monitor);

		// Restore the instructions (if possible).
		if (overwriteInstructions) {
			Disassembler disassembler = Disassembler.getDisassembler(resultProgram, monitor,
				DisassemblerMessageListener.IGNORE);
			monitor.setMessage("Restoring Instructions...   ");
			AddressRangeIterator rangeIter = resultInstructionSet.getAddressRanges();
			int count = 0;
			while (rangeIter.hasNext()) {
				monitor.checkCancelled();
				AddressRange range = rangeIter.next();
				Address min = range.getMinAddress();
				Address max = range.getMaxAddress();
				disassembler.disassemble(min, new AddressSet(min, max), false);
				if (count == PROGRESS_COUNTER_GRANULARITY) {
					monitor.setMessage("Restoring Instructions...   " + min.toString(true));
					count = 0;
				}
			}
		}
	}
<CODE>mergeBytes</CODE> merges byte differences within the specified
 address set.
<br>Note: Any instructions at the equivalent byte addresses in the result program will get cleared and
re-created resulting in the existing references being dropped.

@param originAddressSet the addresses to be merged.
The addresses in this set are derived from the origin program.
@param overwriteInstructions if true affected instructions will be cleared and
re-disassmebled after bytes are modified
@param monitor the task monitor for notifying the user of this merge's
progress.

@throws MemoryAccessException if bytes can't be merged.
@throws CancelledException if user cancels via the monitor.
@throws UnsupportedOperationException if the ProgramMerge translator is not a
"one for one translator".
Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramMerge.java