public OperandRepresentationList getOperandRepresentationList(CodeUnit cu, int opIndex) {

// TODO: Is locking required ??

// TODO: Concurrent modification handling needed ??

		if (cu instanceof Data) {
			if (opIndex == 0) {
				return getDataValueRepresentation((Data) cu);
			}
			return null;
		}

		Program program = cu.getProgram();
		Instruction instr = (Instruction) cu;

		if (!program.getLanguage().supportsPcode()) {
			// Formatted mark-up only supported for languages which support PCode
			return null;
		}

		// Get raw representation list and map of registers contained within it
		List<Object> representationList = instr.getDefaultOperandRepresentationList(opIndex);
		if (representationList == null) {
			return new OperandRepresentationList("<BAD-Instruction>");
		}
		HashMap<Register, Integer> regIndexMap = getRegisterIndexMap(representationList);

		Address address = instr.getMinAddress();
		Function func = instr.getProgram().getFunctionManager().getFunctionContaining(address);

		// Get primary reference for specified operand and determine what if any variable it refers to
		Reference primaryRef = cu.getPrimaryReference(opIndex);
		Variable referencedVariable = null;
		if (primaryRef != null && func != null) {
			referencedVariable = program.getReferenceManager().getReferencedVariable(primaryRef);
		}

		// Handle address replacement within operand
		if (performAddressMarkup(instr, opIndex, func, primaryRef, representationList)) {
			primaryRef = null;
			referencedVariable = null;
		}

		// Handle scalar replacement within operand
		// Scalar replacement is the preferred way of representing references in the absence of an address in the raw representation.
		if (performScalarMarkup(instr, opIndex, func, primaryRef, referencedVariable, regIndexMap,
			representationList)) {
			primaryRef = null;
			referencedVariable = null;
		}

		// Handle possible explicit and inferred register references without scalar offset
		// The corresponding register will be replaced by the associated VariableOffset object.
		if (performRegisterMarkup(instr, opIndex, func, primaryRef, referencedVariable, regIndexMap,
			representationList)) {
			primaryRef = null;
			referencedVariable = null;
		}

		// Show non-consumed primary reference by combining with last sub-operand element
		// This corresponds to what we will refer to as Extended Reference Markup"
		if (performExtendedMarkup(instr, primaryRef, referencedVariable, representationList)) {
			primaryRef = null;
			referencedVariable = null;
		}

		return new OperandRepresentationList(representationList, primaryRef != null);
	}
Returns a formatted list of operand objects for the specified code unit
operand. In the case of Data opIndex=1, this will be a list containing a
single String object (see getDataValueRepresentation(Data)). In the case
of an Instruction, the list will contain a list of Objects, including any
combination of Character, String, VariableOffset, Register, Address,
Scalar, List, LabelString etc.. All objects returned must support the
toString() method.

@param cu code unit
@param opIndex operand index
@return list of representation objects or null for an unsupported
        language.
Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java