The way the emulator code has evolved has made it relatively hard to maintain, to a degree where perhaps only two people would dare to touch it or review patches (maybe except for sufficiently trivial changes). This is actively hindering making any progress there, the more that e.g. even an attempt to start breaking up its monolithic nature has got stalled for a long period of time. The stalls have been so large that even with a little over ten years left I have to raise the question of who would be sensibly maintaining that code once I retire.
A fundamental aspect to have in mind when thinking of solutions is that of limiting redundancy. The giant switch() statement in there combined with heavy use of “goto” is, besides history, primarily attributed due to the goal of re-using code as far as possible. Even now there’s already a lot of duplication because of code often being only similar, but not identical. One approach we would likely want to avoid is that of introducing a significant amount of further indirect calls.