Instructions have been decoded into "micro operations" for a long time. Even the old 8-bit 6502 CPU used a variant of micro-ops. In fact, this was responsible for its very odd behavior when encountering an invalid op code.
On the 6502, op codes were 1 byte long and were followed by a variable number of parameters (operands).
The CPU would load the op code byte from RAM, and decode it into several steps. However, instead of breaking it down into a list, it would look it up in a grid, and if it matched a row in the grid, that row would activate a specific circuit at a specific time (immediately, in 1 cycle time, in 2 cycles time, in 3 cycles time, etc.)
Take for example, the command LDA #$20. This would be stored in RAM as A9 20, and would cause the number 0x20 to be loaded into the accumulator register.
The A9 op code would match the rules in 3 rows in the grid - it would match:
1. Immediately load next byte from RAM and strobe onto the CPU internal bus.
2. In 1 cycle time, strobe the contents of the CPU internal bus into the Accumulator register.
3. In 2 cycles time, continue with the next instruction.
The very similar command LDX #$20 would copy the number 0x20 into the X register. It had the op code A2.
As the command was very similar, it would match some of the same rows in the decoder.
1. Immediately load next byte from RAM and strobe onto the CPU internal bus. (shared with LDA)
2. In 1 cycle time, strobe the contents of the CPU internal bus into the X register.
3. In 2 cycles time, continue with the next instruction. (shared with LDA)
Now, the op code AF was, according to the CPU manual, invalid. But due to the way in which the decoder worked, it would match 4 rows.
1. Immediately load next byte from RAM and strobe onto the CPU internal bus.
2. In 1 cycle time, strobe the contents of the CPU internal bus into the Accumulator register.
3. In 1 cycle time, strobe the contents of the CPU internal bus into the X register.
4. In 2 cycles time, continue with the next instruction.
This would cause the CPU to copy the next byte into both the A and X registers simultaneously. It hadn't been intended by the designers, but it just sort of worked - and when it was discovered was used as a sneaky optimisation by programmers.
Some undefined opcodes would do other weird stuff, due to the effects of simultaneously triggering multiple rules in the instruction decoder, and therefore activating multiple different circuits simultaneously. In some cases, there would be conflicts between various internal CPU circuits causing unpredictable effects.
The other effect that could happen was if an op code matched no rows in the decoder table at all. You'll see in the examples above that the last micro-op is always "continue with next instruction". If the op code didn't match a rule which said "continue", then the CPU wouldn't continue, and would just stop until it was power cycled.