protected AssemblyResolution tryCatenationExpression(
			AbstractAssemblyResolutionFactory<?, ?> factory, OrExpression exp, MaskedLong goal,
			Map<String, Long> vals, AssemblyResolvedPatterns cur, Set<SolverHint> hints,
			String description) throws SolverException {
		/*
		 * If OR is being used to concatenate fields, then we can solve with some symbolic
		 * manipulation. We'll descend to see if this is a tree of ORs with SHIFTs or fields at the
		 * leaves. If it is, we can derive the layout of the composite field and solve each
		 * component independently.
		 */
		Map<Long, PatternExpression> fields = new TreeMap<>();
		collectComponentsOr(exp, 0, fields, vals, cur);
		fields.computeIfAbsent(0L, __ -> new ConstantValue(0));
		fields.put(64L, new ConstantValue(0));
		long lo = 0;
		PatternExpression fieldExp = null;
		AssemblyResolvedPatterns result = factory.nop(description);
		try (DbgCtx dc = dbg.start("Trying solution of field catenation")) {
			dbg.println("Original: " + goal + ":= " + exp);
			for (Map.Entry<Long, PatternExpression> ent : fields.entrySet()) {
				long hi = ent.getKey();
				if (hi == 0) {
					fieldExp = ent.getValue();
					continue;
				}

				dbg.println("Part(" + hi + ":" + lo + "]:= " + fieldExp);
				MaskedLong part = goal.shiftLeft(64 - hi).shiftRightPositional(64 - hi + lo);
				dbg.println("Solving: " + part + ":= " + fieldExp);
				AssemblyResolution sol = solver.solve(factory, fieldExp, part, vals, cur, hints,
					description + " with shift " + lo);
				if (sol.isError()) {
					return sol;
				}
				result = result.combine((AssemblyResolvedPatterns) sol);
				if (result == null) {
					throw new SolverException("Solutions to individual fields produced conflict");
				}

				lo = hi;
				fieldExp = ent.getValue();
			}
		}
		return result;
	}
Solves expressions of the form {@code A | B}
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/assembler/sleigh/expr/OrExpressionSolver.java