Live data from Hacker News

Pushing the limits of RISC-V emulation

shuklaayu.sh

11–20 of 36 posts

Re: Pushing the limits of RISC-V emulation

#11
post #10

The coolest interpreter technique I saw was one that put instruction bodies in static functions which the "compiler" main loop would memcpy the body of the function out to straight-line code that would be executed from memory - a poor man's jit. All instruction functions had the same args and gcc would emit position independent code with the same predictable register calling convention. Brittle as hell, sure, but gre…

Sounds like a copy and patch JIT ( https://en.wikipedia.org/wiki/Copy-and-patch ). The python interpreter was experimenting with this and it provides a decent speedup.

Re: Pushing the limits of RISC-V emulation

#12
post #10

The coolest interpreter technique I saw was one that put instruction bodies in static functions which the "compiler" main loop would memcpy the body of the function out to straight-line code that would be executed from memory - a poor man's jit. All instruction functions had the same args and gcc would emit position independent code with the same predictable register calling convention. Brittle as hell, sure, but gre…

Sounds like a copy and patch JIT ( https://en.wikipedia.org/wiki/Copy-and-patch ). The python interpreter was experimenting with this and it provides a decent speedup.

Odd that the Wikipedia article gives 2021 as the first description of this technique when it is far, far older than that. I worked with a software rasterizer JIT that used it in ~2003 and I thought similar techniques were used in the classic MacOS m68k emulator on PowerPC.

Re: Pushing the limits of RISC-V emulation

#13
I was not impressed by author’s surprise that original emulation ran at 1/10th speed. For the past 50 years, that’s usually the target for calling (“unaccelerated”) emulation good enough. Especially for architectures that are current or in development or otherwise require some sort of instruction translation.

The last 30 years we’ve seen innovations like dynamic recompilation, fat binaries, JIT VMs, and profile guided optimization. So that has created an expectation of sub-order of magnitude run time performance. It’s a fanciful time we live in.

Re: Pushing the limits of RISC-V emulation

#14
CPU architectures evolve and often get replaces, eg Mac has moved from 68k -> Power -> x86 -> ARM or even Windows PC have also jumped from 32 to 64 bits and the same is also true of SIMD.

Why dont O/S support executables with something like LLVM binaries and generate the native code at load time ?

This would solve so many problems including the need for emulators, because all binaries would work on all CPUS, and the OS would produce the best code at load time.

No more cpu detection, vector stuff always works on the latest & widest instructions that are available. CPUs can also retired old legacy instructions without worry and more.

Re: Pushing the limits of RISC-V emulation

#15
post #10

The coolest interpreter technique I saw was one that put instruction bodies in static functions which the "compiler" main loop would memcpy the body of the function out to straight-line code that would be executed from memory - a poor man's jit. All instruction functions had the same args and gcc would emit position independent code with the same predictable register calling convention. Brittle as hell, sure, but gre…

qemu used to use that technique, but as you note, it was pretty brittle. They switched to the more traditional TCG backend.

Re: Pushing the limits of RISC-V emulation

#16
post #4

Earlier quoted context omitted.

How do you differentiate the two? What is the benefit of such a distinction? Why not use eg threaded emulation vs recompiled emulation?

Emulation visits instructions as they are executed. Static recompilation will (at translation time) visit instructions that can be discovered, even if they never run. eg: if (rand64() == 0x123456789abcdef0ull) baz = bar; an emulator will likely never visit that assignment. A static recompiler will translate it.

IDK, a lot of the emulators I've seen and a couple I've written will visit that. Not everything is built on simple traces, but a lot of the time will translate more complex graphs at a time.

Re: Pushing the limits of RISC-V emulation

#17

CPU architectures evolve and often get replaces, eg Mac has moved from 68k -> Power -> x86 -> ARM or even Windows PC have also jumped from 32 to 64 bits and the same is also true of SIMD. Why dont O/S support executables with something like LLVM binaries and generate the native code at load time ? This would solve so many problems including the need for emulators, because all binaries would work on all CPUS, and the…

Would that support self modifying code?

Re: Pushing the limits of RISC-V emulation

#18

CPU architectures evolve and often get replaces, eg Mac has moved from 68k -> Power -> x86 -> ARM or even Windows PC have also jumped from 32 to 64 bits and the same is also true of SIMD. Why dont O/S support executables with something like LLVM binaries and generate the native code at load time ? This would solve so many problems including the need for emulators, because all binaries would work on all CPUS, and the…

This does exist, we call it Java (or C# or probably a dozen other implementations)

The big tradeoff you're making is that you have significantly less time to run your optimizer, since not everybody has a beefy machine or the patience to wait a day for their browser to start first time.

You could try doing optimization ahead of time, but I think (I could be wrong here) you would inevitably end up adding in some CPU assumptions if you went much further. This also somewhat conflicts with an advantage of VM based execution, that new optimizations apply to old binaries.

I'll also note that hand rolled assembly/SIMD code still beats compilers at the extreme end and you would either have to throw that away, or get all the disadvantages mentioned above without all the advantages

Re: Pushing the limits of RISC-V emulation

#19

CPU architectures evolve and often get replaces, eg Mac has moved from 68k -> Power -> x86 -> ARM or even Windows PC have also jumped from 32 to 64 bits and the same is also true of SIMD. Why dont O/S support executables with something like LLVM binaries and generate the native code at load time ? This would solve so many problems including the need for emulators, because all binaries would work on all CPUS, and the…

«Why dont O/S support executables with something like LLVM binaries and generate the native code at load time ?»

I've wondered this too. I can think of two systems "IBM i" (formerly OS/400) [1] and Oberon "Slim Binaries" [2] off the top of my head. I suspect that the answer to your question is some mix of path dependence and engineering trade-offs.

[1] https://en.wikipedia.org/wiki/IBM_i [2] https://dl.acm.org/doi/pdf/10.1145/265563.265576

For example, if the system has unix-style paged virtual memory (which Oberon did not), it's probably convenient to be able to directly map pages of native instructions into memory without needing to translate or massage them first.

In the case of "IBM i", which I've only ever read about, it sounds like it moves complexity from e.g. the compiler into the loader and so closer to the Kernel of the operating system. If I wanted to better understand the net cost/benefit analysis of this design I'd look for more detail on work done to port to PowerPC.

Re: Pushing the limits of RISC-V emulation

#20

CPU architectures evolve and often get replaces, eg Mac has moved from 68k -> Power -> x86 -> ARM or even Windows PC have also jumped from 32 to 64 bits and the same is also true of SIMD. Why dont O/S support executables with something like LLVM binaries and generate the native code at load time ? This would solve so many problems including the need for emulators, because all binaries would work on all CPUS, and the…

It does exist in LLVM and is called Bitcode, a binary format for the LLVM IR - https://llvm.org/docs/BitCodeFormat.html

Apple used to require apps submitted to its iOS App Store to be in the Bitcode format, and they would «recompile» the Bitcode into the exact user's iPhone CPU architecture at the download time – pretty much what OS/400 does. For reasons unknown, they have discontinued Bitcode.

Post reply on HN