For bus snooping, I would suggest using a microcontroller which, while watching the bus, will be devoting all its energy to that task; if any sort of interrupt response will be needed while the bus is being monitored, use a separate processor for the bus monitoring and the other tasks. The bus-monitoring processor could probably act as an SPI slave while it is monitoring the bus, if none of the things it is asked to do while monitoring the bus would be overly complicated [e.g. if the only thing the master ever wants it to do is say whether any interesting bus cycle has happened and, if so, what data was transferred then]. Note that the firmware for the bus-monitoring processor would likely have to be written in machine code and might look something like this:
bl R12 ; Assume R12 holds address of bus-polling rou
ldrb r0,[r11,#SPI_REGS_OFS] ; Assume R11 always holds base of SPI peripheral
; Insert table of 15 jump addresses here
dc.w CMD00_HANDLER, CMD01_HANDLER, CMD02_HANDLER, ... etc.
sub r0,r8,r9 ; Assume R8 and R9 are queue pointers
bic r8,#256 ; Assume queue is located at address of form xxxx0xxxxxxxx.
ldr r5,[r10,#PORT_OFS] ; Assume R10 always holds port base
and r0,r5,r7 ; Assume R7 always holds mask
cmp r0,r6 ; Assume R0 holds compare value
bic r9,#256 ; Assume queue is located at address of form xxxx0xxxxxxxx.
ldr r0,[r10,#PORT_OFS] ; Assume R10 always holds port base
cmp r5,r6 ; See if anything changed
Note that code never goes very long without a
bl R12 which calls one of the POLL_BUS functions, and none of those take very long before returning. Keeping everything in dedicated registers allows the code to run much faster than would be possible in C. The above code would be designed to capture four-byte records any time the bus state changes to a particular pattern; once it grabs something, it will wait until something on the port (whether masked or not) changes before grabbing the next item.