Inputs, use MATH by looking at X0..X7 as a UNSIGNED BYTE, X0:UB (note, you can use this in any instruction that takes a numeric value not just MATH, even in Data View or Trend View!).
MATH V100 "X0:UB & 0xF"
will read X0..X7 as unsigned BYTE then BIT-WISE-AND it with the hex value 0xF (or 0000_0000_0000_1111 in binary). If you want another bit, just tweak the mask. If you want more than 8 bits, cast as UNSIGNED WORD X0:UW.
Outputs are a little harder, because WRITING you have to maintain the state of the upper 4 bits when writing the lower 4 bits. There are multiple ways to do this, but I would use MATH on Y0:UB
MATH Y0:UB "(Y0:UB & 0xF0) | (V101 & 0xF)"
where V101 has the 4 bit values we want to output in its 4 LSBits. So we bitwise AND it with hex 0xF (V101 & 0xF). So we mask of those values to make them the lower 4 bits of Y0:UB. But we want to maintain the current 4 MSBits of Y0:UB (i.e. Y4..Y7), so we grab the 4 MSbits that are already there by bitwise-ANDing Y0:UB with 0xF0 (or 0000_0000_1111_0000, (Y0:UB & 0xF0)). We're still not done. We want to MERGE those two "nibbles" (half bytes) into a single BYTE, so we use bitwise-OR "|" those two "nibbles" and write that result back out to Y0:UB.