private MaskContainer buildSingleInstructionMask(InstructionMetadata instruction) {

		// Do some initial data validation checks.  If we don't have a valid instruction with
		// valid mask and value arrays, we can't do anything, so just return.
		if (instruction == null) {
			return null;
		}
		if (instruction.getMaskContainer() == null) {
			return null;
		}
		if (instruction.getMaskContainer().getMask() == null ||
			instruction.getMaskContainer().getValue() == null) {
			return null;
		}

		// Now Create the mask/value arrays. Populating these is the main point of this method; these 
		// will be placed in the return object when we're done. Note that they're initialized to
		// be the size of the mask/value arrays in the given instruction; these are guaranteed
		// to be the correct size (if they're not, there's a serious problem).
		byte[] tempMask = new byte[instruction.getMaskContainer().getMask().length];
		byte[] tempValue = new byte[instruction.getMaskContainer().getValue().length];

		//////////////////
		// MNEMONIC
		//////////////////

		// First look at the mnemonic.  If it's supposed to be masked, then we want to leave the 
		// mnemonic portion of the arrays set to 0 (they were set to 0 above, when initialized).  If
		// not masked, then we need to put the actual mnemonic bytes in the temp/value arrays.
		if (!instruction.isMasked()) {
			tempValue = instruction.getMaskContainer().getValue();
			tempMask = instruction.getMaskContainer().getMask();
		}

		//////////////////
		// OPERANDS
		//////////////////

		// Now do for the operands what we just did for the mnemonic; loop over each one and add its
		// mask/value to the main arrays depending on the mask setting.
		for (OperandMetadata operand : instruction.getOperands()) {

			// If masked, then just leave the value of the bits at 0.  Continue to the next
			// operand.
			if (operand.isMasked()) {
				continue;
			}

			// Now do some due diligence with null checks...
			if (operand.getMaskContainer().getValue() == null ||
				operand.getMaskContainer().getMask() == null || tempValue == null ||
				tempMask == null) {
				continue;
			}

			// Everything looks good, so apply the operand masks.
			tempValue = InstructionSearchUtils.byteArrayOr(tempValue,
				operand.getMaskContainer().getValue());
			tempMask =
				InstructionSearchUtils.byteArrayOr(tempMask, operand.getMaskContainer().getMask());
		}

		// Now create a new struct for the mask and return to the caller.
		MaskContainer result;
		try {
			result = new MaskContainer(tempMask, tempValue);
		}
		catch (IllegalArgumentException e) {
			// If we're here, then there's a problem with the mask/value arrays we used to 
			// create the mask container.  Just return null.
			return null;
		}

		return result;
	}
Creates a {@link MaskContainer} object for the given instruction,
containing all the pertinent mask and value information. This mask
container contains the mask/value arrays for the entire instruction, both
mnemonic and operands.

@param instruction the instruction to parse
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/model/InstructionSearchData.java