I believe invalid opcodes are executed as NOPs
Nope. Invalid opcodes have "undefined" results. Even some "valid" opcodes have undefined results.
Clever programmers have been known to figure out what the results are and use those opcodes (very dangerous!) or use the results to detect type of CPU (xx opcode does X on cpu Y, but does X2 on cpu Z)
ARM-based Arduinos may actually trap "invalid opcodes" as errors, and then ... do something.
My favorite CPU used to trap "UnUsed Operations", and used about half of them for implementing operating system calls, and about half were available for the users to write their own instructions. (on this particular CPU, the address calculations were extremely regular and happened before opcode decode, so your user-implemented instructions ended up supporting all the fancy addressing modes of all the normal instructions.)