Cross-architecture compilation is ridiculously hard, and the balance between JITing the code and the resulting code's speed is very, very fine, and often depends per process: you don't know when translating an executable page how much it might be run. It could never execute or it could execute trillions of times. You can't just translate every bit of executable code because you WILL spend more time translating than executing. On the other hand, you need to translate well enough that you have good cache performance, make good use of registers (some are usually reserved for emulation state), and the extremely nasty bit of translating specialized math instructions and SIMD instructions, which often have implementation-specific nastiness that causes issues if you translate naïvely. Add onto that fundamental differences that always arise (e.g. unaligned/aligned loads, memory protection/translation differences/access modes, debug/performance registers, appropriate clock timing when necessary, hardware access.... it's endless) and you find yourself relying on pretty horrific hacks to avoid bad performance.
In short, unless you have specialized hardware for this (Transmeta!) it's going to be a massive undertaking.... so if you're confused by the host code produced by qemu, it's a lot harder to produce than you might think, although the primary reason is that producing better code often is not worth it because of the translation time. There may have been recent work to move some of the research in PL JIT over to translation, e.g. progressively translating better code the more it's run, but I haven't looked in a while.