Live data from Hacker News

Things I learned while writing an x86 emulator (2023)

timdbg.com

21–30 of 135 posts

Re: Things I learned while writing an x86 emulator (2023)

#21

> Writing a CPU emulator is, in my opinion, the best way to REALLY understand how a CPU works Hard disagree. The best way is to create a CPU from gate level, like you do on a decent CS course. (I really enjoyed making a cut down ARM from scratch)

Reading Petzold’s “Code” comes pretty close to, though and is easier.

Re: Things I learned while writing an x86 emulator (2023)

#22

Bonus quirk: there's BSF/BSR, for which the Intel SDM states that on zero input, the destination has an undefined value. (AMD documents that the destination is not modified in that case.) And then there's glibc, which happily uses the undocumented fact that the destination is also unmodified on Intel [1]. It took me quite some time to track down the issue in my binary translator. (There's also TZCNT/LZCNT, which is B…

Can you imagine having to make all this logic work faithfully, let alone fast , in silicon? X86 used to be Intel's moat, but what a nightmarish burden to carry.

Did people just... do this by hand (in software), transistor by transistor, or was it laid out programmatically in some sense? As in, were segments created algorithmically, then repeated to obtain the desired outcome? CPU design baffles me, especially considering there are 134 BILLION transistors or so in the latest i7 CPU. How does the team even keep track of, work on, or even load the files to WORK on the CPUs?

Re: Things I learned while writing an x86 emulator (2023)

#23

> Writing a CPU emulator is, in my opinion, the best way to REALLY understand how a CPU works Hard disagree. The best way is to create a CPU from gate level, like you do on a decent CS course. (I really enjoyed making a cut down ARM from scratch)

OTOH, are you really going to be implementing memory segmenting in your gate-level CPU? I'd say actually creating a working CPU and _then_ emulating a real CPU (warts and all) are both necessary steps to real understanding.

Re: Things I learned while writing an x86 emulator (2023)

#24

Bonus quirk: there's BSF/BSR, for which the Intel SDM states that on zero input, the destination has an undefined value. (AMD documents that the destination is not modified in that case.) And then there's glibc, which happily uses the undocumented fact that the destination is also unmodified on Intel [1]. It took me quite some time to track down the issue in my binary translator. (There's also TZCNT/LZCNT, which is B…

Can you imagine having to make all this logic work faithfully, let alone fast , in silicon? X86 used to be Intel's moat, but what a nightmarish burden to carry.

A lot of this is done in software (microcode). But even with that case, your statement still holds: "Can you imagine having to make all this logic work faithfully, let alone fast, in the chip itself?" Writing that microcode must be fiendishly difficult given all the functional units, out of order execution, register renaming...

Re: Things I learned while writing an x86 emulator (2023)

#25

Intel architecture is loaded with historical artifacts. The switch in how segment registers were used as you went from real mode to protected mode was an incredible hardware hack to keep older software working. I blame Intel for why so many folks avoid assembly language. I programmed in assembly for years using TI's 84010 graphics chips and the design was gorgeous -- simple RISC instruction set, flat address space, a…

If Terry A. Davis is to be trusted, as long as you ignore the legacy stuff, x64 assembly is nice to work with.

Re: Things I learned while writing an x86 emulator (2023)

#26
Interesting read. I have a lot of respect for people who develop emulator for x86 processors. It is a complicated processor and from first hand experience I know that developing and debugging emulators for CPU's can be very challenging. In the past year, I spend some time developing a very limited i386 emulator [1] including some system calls for executing the first steps of live-bootstrap [2], primarily to figure out how it is working. I learned a lot about system calls and ELF.

[1] https://github.com/FransFaase/Emulator/

[2] https://github.com/fosslinux/live-bootstrap/

Re: Things I learned while writing an x86 emulator (2023)

#27
post #24

Earlier quoted context omitted.

Can you imagine having to make all this logic work faithfully, let alone fast , in silicon? X86 used to be Intel's moat, but what a nightmarish burden to carry.

A lot of this is done in software (microcode). But even with that case, your statement still holds: "Can you imagine having to make all this logic work faithfully, let alone fast, in the chip itself?" Writing that microcode must be fiendishly difficult given all the functional units, out of order execution, register renaming...

The crazy parts that were mentioned in the parent comment are all part of the hot path. Microcode handles slow paths related to paging and segmentation, and very rare instructions. Not necessarily unimportant (many common privileged instructions are microcoded) but still rare compared to the usual ALU instructions.

But it's not a huge deal to program the quirky encoding in an HDL, it's just a waste of transistors. The really complicated part is the sequencing of micro operations and how they enter the (out of order) execution unit.

Re: Things I learned while writing an x86 emulator (2023)

#28
post #22

Earlier quoted context omitted.

Can you imagine having to make all this logic work faithfully, let alone fast , in silicon? X86 used to be Intel's moat, but what a nightmarish burden to carry.

Did people just... do this by hand (in software), transistor by transistor, or was it laid out programmatically in some sense? As in, were segments created algorithmically, then repeated to obtain the desired outcome? CPU design baffles me, especially considering there are 134 BILLION transistors or so in the latest i7 CPU. How does the team even keep track of, work on, or even load the files to WORK on the CPUs?

They use EDA (Electronic Design Automation) software, there are only a handful of vendors, the largest probably being Mentor Graphics, now owned by Siemens. So, yes, they use automation to algorithmically build and track/resolve refactors as they design CPUs. CPUs are /generally/ block-type designs these days, so particular functions get repeated identically in different places and can be somewhat abstracted away in your EDA.

It's still enormously complex, and way more complex than the last time I touched this stuff more than 15 years ago.

Re: Things I learned while writing an x86 emulator (2023)

#29
post #24

Earlier quoted context omitted.

Can you imagine having to make all this logic work faithfully, let alone fast , in silicon? X86 used to be Intel's moat, but what a nightmarish burden to carry.

A lot of this is done in software (microcode). But even with that case, your statement still holds: "Can you imagine having to make all this logic work faithfully, let alone fast, in the chip itself?" Writing that microcode must be fiendishly difficult given all the functional units, out of order execution, register renaming...

> A lot of this is done in software (microcode).

No, that's not the case, since >30 years. Microcode is only used for implementing some complex instructions (mostly system instructions). Most regular instructions (and the rest of the core) don't use microcode and their expansions into uOps are hardwired. Also the entire execution unit is hardwired.

There are typically some undocumented registers (MSRs on x86) that can control how the core behaves (e.g., kill switches for certain optimizations). These can then be changed by microcode updates.

Re: Things I learned while writing an x86 emulator (2023)

#30
post #22

Earlier quoted context omitted.

Can you imagine having to make all this logic work faithfully, let alone fast , in silicon? X86 used to be Intel's moat, but what a nightmarish burden to carry.

Did people just... do this by hand (in software), transistor by transistor, or was it laid out programmatically in some sense? As in, were segments created algorithmically, then repeated to obtain the desired outcome? CPU design baffles me, especially considering there are 134 BILLION transistors or so in the latest i7 CPU. How does the team even keep track of, work on, or even load the files to WORK on the CPUs?

It's written in an HDL; IIRC both Intel and AMD use verilog. A modern core is on the order of a million or so lines of verilog.

Some of that will be hand placed, quite a bit will just be thrown at the synthesizer. Other parts like SRAM blocks will have their cad generated directly from a macro and a description of the block in question.

Post reply on HN