41 comments

[ 3.4 ms ] story [ 91.4 ms ] thread
Way too many.
(comment deleted)
I intend to read the 3-volume edition of Intel's developer manual from start to finish, but haven't decided when to do it, before or after TAOCP.
I've written assemblers for about 30 different ISAs (ISAE?)---most of them custom. An ISA (almost always) forms a DAG, where a node is a legal string of {01X} that is producible from the ISA; the 'X' meaning "0 or 1". An encoding is a daughter of another encoding if it has a 0 or 1 whenever the parent has a 0 or 1.

A "projection" is the imposition of a tree-like structure on the DAG, followed by a cut of the tree to make it practicalable in size. Aliasing mnemonics in the tree can cause confusion for the user---or aid in understanding.

These articles are noting that there are many ways to project the x86 ISA.

do you mind going into why you have written so many assemblers?
My grad work was in system programming language design; I used to toy around with VM design, so that meant I was (poorly) designing a lot of ISAs and then writing a lot of assemblers for them. My professional work is unrelated to my grad work, but has still let me expand on that interest. Sorry I'm so vague. Think more along the lines of "python byte code assembler", or somesuch thing.
Do you happen to blog? Would absolutely love to read about best practices, curious situations and so on.
This article makes me kind of wonder wether there are processors that understand two or more unrelated instruction encoding sets.
I vaguely recall reading about someone developing a chip that could run both ARM and x86 code. The idea being that it would run ARM code most of the time at low power, and then power up in order to run x86 code when necessary. I don't know if there was any clever sharing of the silicon, or if it was in fact just an x86 core and an ARM core glued together.

The only thing I can find on it though is this IEEE document reference: http://ieeexplore.ieee.org/document/6136696/

That was Transmeta, which became Nvidia's Project Denver. I think the show stopper is that they were unable to acquire an x86 license.

Anyway, it actually ran neither (the core is more like Itanium) and had a separate chip that JIT compiled ARM and x86 to the internal ISA.

As far as I'm aware, none of Transmeta's x86 stuff became Project Denver. There was definitely licensing of Transmeta technologies, but I believe that was relatively generally applicable patents (well, generally applicable to ICs). There was, however, given the relative size of the semiconductor industry, some ex-Transmeta staff working on Project Denver.

But yes, as far as I'm aware, what killed the x86 support was licensing.

Project Denver still JITs ARM to an internal VLIW architecture I believe. It's pretty Transmeta-like.
Yes, they do. And the influence of Transmeta is clearly there, even if it's not a direct descendent. Ultimately the x86 licensing issue just killed the x86 decode step, AFAIK.
There was also the PPC615 in the mid-90s, done by IBM, which was socket-compatible with the Pentium, and could execute at least PPC32, PPC64, and x86_32 natively (I'm not clear on whether it supported x86_16): the decode step for x86_32, AIUI, essentially decoded it into PPC instructions. It was meant to be competitive with the Pentium in x86-mode, and could change between ISAs at the thread level, I believe. Ultimately it was scrapped as people in charge believed Intel were about to move away from IA-32 and the industry would follow to IA-64 with its IA-32 compatibility.
What do you consider as "unrelated"? For example modern ARMv8 cores understand 3 instruction sets: AArch32, Thumb2 and AArch64. AArch32 and Thumb may be related, but AArch64 is more different (no conditional execution, more registers etc. for example). Though you would perhaps still consider them as related.

EDIT: Similarly, modern x86-64 cores support at least three instruction sets: x86-16 (real mode), x86-32 (protected mode) and x86-64 (long mode). These are related, but at least I claim that x86-16 and x86-64 are very different in practise.

A perhaps better example is Jazelle on older ARM cores, which supported exectuting most of Java VM's instruction set directly on the processor.

Or another example: The instruction set of many processors is separated into several parts that work and encode quite differently. For example the x87 instructions are stack-based instead of register-based. Or I have heard that AltiVec instructions encode and work quite differently from normal PowerPC instructions. The only reason why these are not considered as different instruction sets is that they lie in the same opcode space. If you consider instruction sets that "just lie in the same opcode space, but are otherwise mostly unrelated" as unrelated, then there are some instruction sets that evolved as hybrids of different instruction sets for controlling different functional units.

Or another example is many SoCs contain additional coprocessors and ARM's instruction set contains instruction for controlling them. These coprocessors execute different instruction set. But perhaps you would consider this not as "one processor" but rather several communicating processors on one chip.

TLDR: Define what you mean with "[one] processor" and with "unrelated" in terms of encoding of instructions.

Your examples are all instruction sets that were developed with the idea in mind that they run together with the other instruction sets. What I meant with unrelated is instruction sets that have been developed independently and were not meant to run on the same cpu from the beginning. For instance a cpu that supports both the Risc-V and the Power architecture.
Look again -- he mentioned Jazelle, does that fit the bill?
> What I meant with unrelated is instruction sets that have been developed independently and were not meant to run on the same cpu from the beginning.

Beside umanwizard's comment: What do you consider as "same CPU" here? As I wrote there exist SoCs that can execute multiple instruction sets (for example some DSP at the side of an ARM core, where both instruction sets were developed independently). Do you consider this as "the same CPU" or not and what is the reason why you say "yes" or "no" here?

There was the V20/V30. It was a drop-in replacement for the 8088 that could also execute 8080 (or Z80---it's been awhile since I used one) code (it was also faster at executing 8088 code, which is why a lot of people used it). While the 8088 is descended from the 8080, it's not binary compatible (completely different opcodes) and probably fits your criteria.
It was the Intel 8080 not the Z80 for which the V20/V30 had an emulation mode (just looked it up).

To do some nitpicking on this great example: The Intel 8086/8088 was designed to be assembly source compatible (up to search & replace) to the Intel 8080 (source: https://en.wikipedia.org/w/index.php?title=Intel_8086&oldid=...). People like legulere would thus clearly nitpick that the criterion "instruction sets that have been developed independently" is not satisfied here.

> A perhaps better example is Jazelle on older ARM cores, which supported exectuting most of Java VM's instruction set directly on the processor.

That's interesting. I vaguely remember one of my professors mentioning that one of the original plans for Java was to have processors that could execute the bytecode (somewhat) directly. I wasn't aware any actually existed.

It existed, but went away because Java bytecode is semantically a terrible language for a CPU to execute. Jitting it down to something that fits hardware better greatly increases speed, so the best you can do is move that jit into hardware, and even then you are hamstrung by the verbosity of the bytecode.
> Java bytecode is semantically a terrible language for a CPU to execute

As someone who's not a jvm or hw person: why's that?

Java bytecode is stack-based and serializes all execution in a thread. In CPU design, you get speed by doing things in parallel, and doing the transformation of Java bytecode stream to some format that allows more instruction-level parallelism takes more time than is available in a CPU frontend.
The NEC V20/V30 chips were 8086 clones, but unusually they had an 8080 emulation mode. I recall that the registers were common, eg. %bx (8086) and BC (8080) were the same register when you switched between modes.

The "killer feature" was that you could run CP/M programs on your PC. As long as the CP/M programs weren't "naughty" and didn't use Z80 instructions (a different superset of 8080). CP/M itself had system calls which emulated the Z80 instructions (mainly LDIR), which could be "accelerated" if the processor was a real Z80, but of course programs occasionally ignored this and just used the Z80 instructions directly.

https://en.wikipedia.org/wiki/NEC_V20

Depending on your definition of "processor", most SoCs that have an integrated CPU and GPU may fit the bill.
> ISAs (ISAE?)

-ae only if the word is a) not an abbreviation, b) Latin, and c) a-declension.

Pretty sure GP was joking. But anyway, my favorite word to throw out there in fun little pedantic conversations like this = octopus, which ends up ! actually being octopi like most people think, but rather octopodes due to it being from Greek & ! Latin.
Grammar is always fun, even more so when you start mixing several languages.
Especially in the same word! coughtelevisioncough
hexadecimal, was originally and correctly sexadecimal, but when it got wider use somehow was turned into hexadecimal instead of the also correct hexagecimal.
I support languages fully 'thieving' and owning words that they copy (not borrow) from other languages.

It might be octopodes in those other languages, but octopi is the pattern most expect from the current structure and therefore it is more correct; scholars of exceptions be forgiven for their pedantic ways.

It supports up to 4,294,967,296 instructions.
Where did you get that number from? Instructions are not limited to 31 bits in length
Sorry, if I may sound off-topic, but it seems that XED-downloads aren't working at all.
One question this left me: are we leaving performance off the table by using compilers that are only using a "standard" subset of the possible instructions out there?
Define "we". I think there is definitely some applications doing this.

Last I checked, using default GCC settings you can drastically change the performance of the resulting app by passing different flags. This obviously depends a lot on the app, but I recall a simple raytracing program I wrote in C++ in University being sped up quite a bit when I passed it flags to optimize for Pentium4+, because it leveraged certain SSE instructions.

MSVC++ with optimizations turned on actually bundles multiple copies of the binary in the resulting .exe file, and is able to pick the optimal one (based on the ISA extensions your CPU supported) at runtime. I'm sure you can do something comparable with binaries produced by GCC and CLang.

Now.. do I think this improperly optimized binaries are a problem plaguing us? No. Because the large native applications that would really benefit (such as Chrome/V8) have already dealt with this. The smaller apps (think a small GTK app like gedit) won't see a noticeable performance benefit. And most newer, consumer applications (Spotify, Slack, Skype) are written in something like Node anyways.

tldr; What is the answer? Curious.
The post begins:

> It’s surprisingly hard to give a good answer (the question was raised in this article). It depends on how you count, and the details are interesting (to me anyway).