public static String convertMaskToHexString(long msk, int n, boolean truncate, int spaceevery,
			String spacer) {
		StringBuilder sb = new StringBuilder(n * 4);
		int shamt = (n * 4 - 4);
		final long LEFT_NIBBLE = 0x0fL << shamt;
		final long LEFT_BIT = 0x08L << shamt;

		for (int i = 0; i < n; i++) {
			if (!truncate && spaceevery != 0 && i != 0 && i % spaceevery == 0) {
				sb.append(spacer);
			}
			long m = msk & LEFT_NIBBLE;
			if (m == 0L) { // fully-excluded nibble: either truncate or append 0
				if (truncate) {
					continue;
				}
				sb.append('0');
				msk <<= 4;
			}
			else if (m == LEFT_NIBBLE) { // fully-included nibble: append F
				sb.append('F');
				msk <<= 4;
			}
			else { // partially-defined nibble: append bracketed bits
				sb.append('[');
				for (int j = 0; j < 4; j++) {
					if ((msk & LEFT_BIT) == 0) {
						sb.append('0');
					}
					else {
						sb.append('1');
					}
					msk <<= 1;
				}
				sb.append(']');
			}
			truncate = false;
		}
		if (sb.length() == 0 && n != 0) {
			return "X";
		}
		return sb.toString();
	}
Convert a mask to a hexadecimal-ish string.

Converts the mask in a similar way to
{@link #convertMaskedValueToHexString(long, long, int, boolean, int, String)}.
Philosophically, it is hexadecimal, but the only valid digits are 0 and F. Any
partially-included nibble will be broken down into bracketed bits. Displaying masks in this
way is convenient when shown proximal to related masked values.

@param msk the mask
@param n the number of nibbles, starting at the right
@param truncate true if leading Xs may be truncated
@param spaceevery how many nibbles in spaced groups, 0 for no spaces
@param spacer the group separator, if applicable
@return the string representation

@see #convertMaskedValueToHexString(long, long, int, boolean, int, String)
@see #convertHexStringToMaskedValue(AtomicLong, AtomicLong, String, int, int, String)
Ghidra/Framework/Generic/src/main/java/ghidra/util/NumericUtilities.java