public int getStackOffset(Instruction cu, int opIndex) {
		int offset = 0;
		int offsetReg = 0;
		Register offReg = null;
		Scalar s = null;
		Object obj[] = cu.getOpObjects(opIndex);
		for (int i = 0; obj != null && i < obj.length; i++) {
			if (obj[i] instanceof Scalar) {
				Scalar newsc = (Scalar) obj[i];
				if (s != null) {
					return Function.INVALID_STACK_DEPTH_CHANGE;
				}
				// choose the biggest value....
				if (Math.abs(offset) < newsc.getUnsignedValue()) {
					offset = (int) newsc.getSignedValue();
					s = newsc;
				}
			}

			// check if any register is the stack pointer
			// if it is, need to compute stack depth offset for function
			//
			if (obj[i] instanceof Register) {
				Register reg = (Register) obj[i];
				int depth = getRegDepth(cu.getMinAddress(), reg);
				if (depth != Function.INVALID_STACK_DEPTH_CHANGE &&
					depth != Function.UNKNOWN_STACK_DEPTH_CHANGE) {
					offReg = reg;
					offsetReg = depth;
				}
			}
		}

		// must have a register that has the stack depth in it and a scalar
		if (offReg == null || s == null) {
			return Function.INVALID_STACK_DEPTH_CHANGE;
		}
		offset += offsetReg;

		return offset;
	}
Follow the flows of the subroutine, accumulating information about the
stack pointer and any other register the stack pointer is assigned to.

@param func
           function to analyze
@param monitor
           monitor to provide feedback and cancel
@throws CancelledException if monitor canceled
Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CallDepthChangeInfo.java