protected AssemblyResolution tryCircularShiftExpression(
			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 accomplish a circular shift, then we can apply a clever solver.
		// We'll match against the patterns: (f << (C - g)) | (f >> g)
		//                                   (f >> (C - g)) | (f << g)
		int leftdir; // 0 is left, 1 is right
		// "left" and "right" are about to get really overloaded....
		if ((exp.getLeft() instanceof LeftShiftExpression &&
			exp.getRight() instanceof RightShiftExpression)) {
			leftdir = 0;
		}
		else if (exp.getLeft() instanceof RightShiftExpression &&
			exp.getRight() instanceof LeftShiftExpression) {
			leftdir = 1;
		}
		else {
			throw new SolverException("Not a circular shift");
		}

		BinaryExpression left = (BinaryExpression) exp.getLeft();
		BinaryExpression right = (BinaryExpression) exp.getRight();
		PatternExpression expValu1 = left.getLeft();
		PatternExpression expValu2 = right.getLeft();
		if (!expValu1.equals(expValu2)) {
			throw new SolverException("Not a circular shift");
		}

		PatternExpression expShift = null;
		int size = -1, dir = -1;

		PatternExpression s1 = left.getRight();
		PatternExpression s2 = right.getRight();
		if (s1 instanceof SubExpression) {
			SubExpression sub = (SubExpression) s1;
			expShift = sub.getRight();
			if (expShift.equals(s2)) {
				PatternExpression c = sub.getLeft();
				MaskedLong cc = solver.getValue(c, vals, cur);
				if (cc.isFullyDefined()) {
					// the left side has the subtraction, so the overall shift is the opposite
					// of the direction of the shift on the left
					dir = 1 - leftdir;
					size = (int) cc.longValue();
				}
			}
		}
		if (dir == -1 && s2 instanceof SubExpression) {
			SubExpression sub = (SubExpression) s2;
			expShift = sub.getRight();
			if (expShift.equals(s1)) {
				PatternExpression c = sub.getLeft();
				MaskedLong cc = solver.getValue(c, vals, cur);
				if (cc.isFullyDefined()) {
					// the right side has the subtraction, so the overall shift is the same
					// as the direction of the shift on the left
					dir = leftdir;
					size = (int) cc.longValue();
				}
			}
		}
		if (dir == -1) {
			throw new SolverException("Not a circular shift (or of known size)");
		}

		// At this point, I know it's a circular shift
		dbg.println("Identified circular shift: value:= " + expValu1 + ", shift:= " + expShift +
			", size:= " + size + ", dir:= " + (dir == 1 ? "right" : "left"));
		return solveLeftCircularShift(factory, expValu1, expShift, size, dir, goal, vals, cur,
			hints, description);
	}
Solves expressions of the form {@code A | B}
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/assembler/sleigh/expr/OrExpressionSolver.java