private void _evaluateCurrentOp() throws DWARFExpressionException {
		int opcode = currentOp.getOpCode();
		if (DWARFExpressionOpCodes.UNSUPPORTED_OPCODES.contains(opcode)) {
			throw new DWARFExpressionException(
				"Can not evaluate unsupported opcode " + DWARFExpressionOpCodes.toString(opcode));
		}

		if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
			push(currentOp.getRelativeOpCodeOffset(DW_OP_lit0));
		}
		else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
			// Retrieve value held in register X and add offset from operand and push result on stack.
			// Fake it using zero as register value.
			// Mainly only useful if offset is zero or if non-zero the register happens to
			// be the stack pointer.
			long offset = currentOp.getOperandValue(0);
			push(0 /*fake register value */ + offset);
			lastRegister = currentOp.getRelativeOpCodeOffset(DW_OP_breg0);

			if (lastRegister == registerMappings.getDWARFStackPointerRegNum()) {
				lastStackRelative = true;
			}
			else {
				useUnknownRegister = true;
				if (offset == 0) {
					// if offset is 0, we can represent the location as a ghidra register location
					// also implies a deref by the user of this location info
					registerLoc = true;
				}
			}

		}
		else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) {
			push(0);// TODO: not sure why we are pushing a zero on stack, not part of DWARF std.
			lastRegister = currentOp.getRelativeOpCodeOffset(DW_OP_reg0);
			registerLoc = true;
		}
		else if (opcode == DW_OP_regx) {
			push(0);// TODO: not sure why we are pushing a zero on stack, not part of DWARF std.
			lastRegister = (int) currentOp.getOperandValue(0);
			registerLoc = true;
		}
		else {
			switch (opcode) {
				case DW_OP_addr:
				case DW_OP_const1u:
				case DW_OP_const2u:
				case DW_OP_const4u:
				case DW_OP_const8u:
				case DW_OP_const1s:
				case DW_OP_const2s:
				case DW_OP_const4s:
				case DW_OP_const8s:
				case DW_OP_constu:
				case DW_OP_consts:
					push(currentOp.getOperandValue(0));
					break;
				// Register Based Addressing
				case DW_OP_fbreg:
					push(frameOffset + currentOp.getOperandValue(0));
					lastStackRelative = true;
					break;
				// Stack Operations
				case DW_OP_dup:
					push(peek());
					break;
				case DW_OP_drop:
					pop();
					break;
				case DW_OP_pick: {
					long index = currentOp.getOperandValue(0);
					if (index >= stack.size()) {
						throw new DWARFExpressionException(
							"Invalid index for DW_OP_pick: " + index);
					}
					dw_op_pick((int) index);

					break;
				}
				case DW_OP_over: {
					if (stack.size() < 2) {
						throw new DWARFExpressionException(
							"Not enough items on stack[size=" + stack.size() + "] for DW_OP_over");
					}
					dw_op_pick(1);

					break;
				}
				case DW_OP_swap: {
					long firstValue = pop();
					long secondValue = pop();
					push(firstValue);
					push(secondValue);
					break;
				}
				case DW_OP_rot: {
					long firstValue = pop();
					long secondValue = pop();
					long thirdValue = pop();
					push(firstValue);
					push(thirdValue);
					push(secondValue);
					break;
				}
				case DW_OP_deref: {
					isDeref = true;
					// Real deref should pop the top value from stack, deref it,
					// and push value found at that address on stack.
					// Since we can only handle the subset of deref usages that are
					// register or framebased, leave the stack alone so that the
					// register or framebase offset can be accessed.
					break;
				}

				case DW_OP_call_frame_cfa: {
					push(registerMappings.getCallFrameCFA());
					lastStackRelative = true;
					break;
				}

					// Arithmetic and Logical Operations
				case DW_OP_abs: {
					push(Math.abs(pop()));
					break;
				}
				case DW_OP_and: {// bitwise and
					long firstValue = pop();
					long secondValue = pop();
					push(firstValue & secondValue);
					break;
				}
				case DW_OP_div: {
					long firstValue = pop();
					long secondValue = pop();
					if (firstValue == 0) {
						throw new DWARFExpressionException("Divide by zero");
					}
					push(secondValue / firstValue);
					break;
				}
				case DW_OP_minus: {
					long firstValue = pop();
					long secondValue = pop();
					push(secondValue - firstValue);
					break;
				}
				case DW_OP_mod: {
					long firstValue = pop();
					long secondValue = pop();
					if (firstValue == 0) {
						throw new DWARFExpressionException("Divide by zero");
					}
					push(secondValue % firstValue);
					break;
				}
				case DW_OP_mul: {
					long firstValue = pop();
					long secondValue = pop();
					push(firstValue * secondValue);
					break;
				}
				case DW_OP_neg: {
					long firstValue = pop();
					push(-firstValue);
					break;
				}
				case DW_OP_not: {// bitwise neg
					long firstValue = pop();
					push(~firstValue);
					break;
				}
				case DW_OP_or: {// bitwise or
					long firstValue = pop();
					long secondValue = pop();
					push(firstValue | secondValue);
					break;
				}
				case DW_OP_plus: {
					long firstValue = pop();
					long secondValue = pop();
					push(firstValue + secondValue);
					break;
				}
				case DW_OP_plus_uconst: {
					long firstValue = pop();
					long value = currentOp.getOperandValue(0);
					push(firstValue + value);
					break;
				}
				case DW_OP_shl: {
					long firstValue = pop();
					long secondValue = pop();
					push(secondValue << firstValue);
					break;
				}
				case DW_OP_shr: {
					long firstValue = pop();
					long secondValue = pop();
					push(secondValue >>> firstValue);
					break;
				}
				case DW_OP_shra: {
					long firstValue = pop();
					long secondValue = pop();
					push(secondValue >> firstValue);
					break;
				}
				case DW_OP_xor: {
					long firstValue = pop();
					long secondValue = pop();
					push(firstValue ^ secondValue);
					break;
				}
					// Control Flow Operations, values treated as signed for comparison
				case DW_OP_le: {
					long firstValue = pop();
					long secondValue = pop();
					push((secondValue <= firstValue) ? 1L : 0L);
					break;
				}
				case DW_OP_ge: {
					long firstValue = pop();
					long secondValue = pop();
					push((secondValue >= firstValue) ? 1L : 0L);
					break;
				}
				case DW_OP_eq: {
					long firstValue = pop();
					long secondValue = pop();
					push((secondValue == firstValue) ? 1L : 0L);
					break;
				}
				case DW_OP_lt: {
					long firstValue = pop();
					long secondValue = pop();
					push((secondValue < firstValue) ? 1L : 0L);
					break;
				}
				case DW_OP_gt: {
					long firstValue = pop();
					long secondValue = pop();
					push((secondValue > firstValue) ? 1L : 0L);
					break;
				}
				case DW_OP_ne: {
					long firstValue = pop();
					long secondValue = pop();
					push((secondValue != firstValue) ? 1L : 0L);
					break;
				}
				case DW_OP_skip: {
					long destOffset = currentOp.getOperandValue(0) + currentOp.getOffset();
					int newStep = expr.findOpByOffset(destOffset);
					if (newStep == -1) {
						throw new DWARFExpressionException("Invalid skip offset " + destOffset);
					}
					currentOpIndex = newStep - 1;// 1 before the target op index because the for() loop will ++ the index value
					break;
				}
				case DW_OP_bra: {
					long destOffset = currentOp.getOperandValue(0) + currentOp.getOffset();
					long firstValue = pop();
					if (firstValue != 0) {
						int newStep = expr.findOpByOffset(destOffset);
						if (newStep == -1) {
							throw new DWARFExpressionException("Invalid bra offset " + destOffset);
						}
						currentOpIndex = newStep - 1;// 1 before the target op index because the for() loop will ++ the index value
					}
					break;
				}

					// Special Operations
				case DW_OP_nop: {
					break;
				}
				case DW_OP_stack_value:
					// This op is a flag to the debugger that the requested value does not exist in memory
					// (on the host) but that the result of this expression gives you value
					dwarfStackValue = true;
					break;

				case DW_OP_addrx:
					try {
						long addr = dprog.getAddress(DWARFForm.DW_FORM_addrx,
							currentOp.getOperandValue(0), cu);
						push(addr);
						break;
					}
					catch (IOException e) {
						throw new DWARFExpressionException(
							"Invalid indirect address index: " + currentOp.getOperandValue(0));
					}
				case DW_OP_constx: // same as addrx, but different relocation-able specifications
					try {
						long addr = dprog.getAddress(DWARFForm.DW_FORM_addrx,
							currentOp.getOperandValue(0), cu);
						push(addr);
						break;
					}
					catch (IOException e) {
						throw new DWARFExpressionException(
							"Invalid indirect address index: " + currentOp.getOperandValue(0));
					}

				default:
					throw new DWARFExpressionException("Unimplemented DWARF expression opcode " +
						DWARFExpressionOpCodes.toString(opcode));
			}
		}
	}
@param _expr
@param stackArgs - pushed 0..N, so stackArgs[0] will be deepest, stackArgs[N] will be topmost.
@return
@throws DWARFExpressionException
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf/expression/DWARFExpressionEvaluator.java