22
$\begingroup$

The question is basically in the title. I know that a computers hardware is of course some physical object, where as the interpreter is some abstract thing that does something abstract with the code it is given. Yet, can we say that the way the processor is build is the implementation of an interpreter?

Machine language is a sequence of physical states (0s and 1s ) on some physical memory, and if this physical states order follows certain rules (the syntax of the machine language) then the processor is build in a way that naturally leads to performing calculation steps (and changing some of the memory), e.g. "run" the programm.

As this question's answer points out, compilers translate from one language to another, and interpreters for each language "run" the programm. It would be just consistent if this stretches down to machine language as well, and that's why I'm asking.

If one can make the analogy, when would it break down? What features of language semantics (given by the interpreter), for example expressions and values, are there that we can't find at the physical level anymore? In what way does the processor behave differently from what is expected of an interpreter?

$\endgroup$
11

9 Answers 9

32
$\begingroup$

It's not such a bad way of looking at things.

On most modern CPUs, the instruction set architecture (ISA for short) is abstract, in the sense that it doesn't dictate that it must be implemented using certain hardware techniques or it is not a compliant implementation. Nothing in the ISA specification specifies whether or not it uses register renaming, or branch prediction, or whether vector instructions are parallel or pipeline-streaming, or even whether the core is scalar or superscalar.

Indeed, on many modern CPUs, there is a certain amount of translation from the ISA into an internal representation to be executed more efficiently, such as Intel's micro-operations (uOps for short).

$\endgroup$
9
  • 1
    $\begingroup$ Does the ISA being abstract make it less quIalified for being an interpreter? Do interpreters implementations usually comply to some standard? I try to understand how the information you gave fit's into my question. $\endgroup$ Sep 19, 2021 at 12:15
  • 15
    $\begingroup$ @Quantumwhisp I think what Pseudonym meant is actually contrary to what you wrote: the ISA being abstract makes the hardware more qualified to be regarded as an interpreter $\endgroup$
    – ciamej
    Sep 19, 2021 at 18:54
  • 1
    $\begingroup$ Exactly that. It may be useful to compare with more specialised ISAs (e.g. those of microcontrollers), where worst-case cycle counts form part of the specification. This can sometimes be important, for example in certain hard real-time applications where worst-case interrupt delivery time must be minimised. In situations like this, it does partly dictate what kind of hardware technology can be used to implement the instruction set. $\endgroup$
    – Pseudonym
    Sep 19, 2021 at 23:58
  • 5
    $\begingroup$ @Corbin good point ;-): The OP was asking about the bare metal and is diverted to the description of another abstract machine. But I think the point is that what you "code assembler against" is always an abstract machine, and the hardware factually interprets it -- be it because it directly executes literally what's coded or because it transforms it again beforehand. A good example of the idea is a Lisp machine which does a lot of the interpreting work in hardware. One could still say "it interprets Lisp". $\endgroup$ Sep 20, 2021 at 10:49
  • 2
    $\begingroup$ @Joshua There is a fuzzy line between "compiler" and "interpreter", but the way I usually use the terms is whether translation is static (ahead of time) or dynamic (as execution proceeds). $\endgroup$
    – Pseudonym
    Sep 22, 2021 at 1:24
8
$\begingroup$

No, it would not be wrong. Indeed, we can use the Futamura projections to help us understand the situation.

The first Futamura projection says that if we specialize hardware with some native machine code, then we get a standalone executable. For example, classic video-game consoles combined an interpreter in the console with native code in each game cartridge, so that plugging a cartridge into a console resulted in an executable system. As other answers point out, computability theory implies that we can write (slow) software which is equivalent to the hardware in effects, and indeed emulators exist for most classic consoles.

Edit: A Futamura specializer is a specific sort of program which takes two unevaluated programs and returns their composition. Sometimes it is called a Kleene compositor due to its relationship with Kleene's parameter theorem (the $S^m_n$ theorem). For more details, see Piponi (with helpful pictures); for even more details, see "Partial Evaluation and Automatic Program Generation". In older computers, inserting a cartridge would close electronic circuits, connecting daughterboard to motherboard and allowing all of the chips in the cartridge to communicate with the chips in the host. This is Futamura specialization; a piece of non-functional hardware was added to existing hardware in order to create a system which is limited in functionality but relatively fast at execution.

The second Futamura projection says that if we specialize the specialization process itself with the interpreter as the curried argument, then we get a compiler. I'll extend the video-game example. A local bar has a large selection of classic games; if we ask the bartender to load a cartridge, then the bartender will allocate a console and deliver controllers. In essence, the bartender is a Futamura compiler.

Less facetiously, we could imagine a compiler in the traditional sense, compiling high-level programmer expressions to native code, but generated using Futamura projections. If this compiler's underlying interpreter is some hardware, then this implies that the compiler will directly call that hardware in order to partially evaluate the static parts of its input programs. And, if one thinks about it for a moment, any partially-evaluating compiler is doing something morally equivalent to this; Futamura would just require that the emulation of instructions is done in a faithful way, using instructions equivalent to the original hardware.

$\endgroup$
5
  • 1
    $\begingroup$ When you say "native code" in this context, you're talking about custom-designed hardware, e.g. to accelerate some portion of the game logic? The question is already talking about CPUs executing machine code, although 8-bit micros (including those used in early game consoles) often were microcoded designs, where being an "interpreter" for machine code was in some ways an accurate description of how the hardware really worked. $\endgroup$ Sep 22, 2021 at 8:57
  • $\begingroup$ @PeterCordes: "native code" is a synonym for machine code. Also, as I pointed out in another comment, it is a homuncular fallacy to believe that a hardware interpreter's internal design is relevant, even when it defines micro-operations. $\endgroup$
    – Corbin
    Sep 22, 2021 at 15:04
  • 1
    $\begingroup$ Oh, so when you say "specialize", you mean "provide code for, making the generic game console into an implementation of an Asteroids, Breakout, or Super Mario Bros game machine". Ok, I see how your terminology works now. $\endgroup$ Sep 22, 2021 at 15:18
  • $\begingroup$ @PeterCordes: It sounds like you grok it, but it was far too difficult, and for that I apologize. I've added the word "machine" to "native code", and I've added an entire paragraph about Futamura specialization with external resources. Thanks for your feedback! $\endgroup$
    – Corbin
    Sep 22, 2021 at 15:36
  • $\begingroup$ What about the Futurama Projections? $\endgroup$
    – Penguin9
    Oct 9, 2021 at 12:46
7
$\begingroup$

You could look at it that way. But traditionally, the term "interpreter" is usually used to refer to software, not hardware.

There are CPU emulators, these can definitely be considered to be interpreters of the processor machine language.

The distinction between hardware and software implementations is useful in practice because it dictates how easy it is to make changes. If there's a bug in a hardware CPU, you will likely have to replace the computer or processor chip to address it (unless there are software workarounds). But if there's a problem in a software interpreter, you can just install an update (which has become easier over the years, as digital media became more compact and then migrated to Internet distribution). This means that hardware development requires more stringent specifications and testing -- bugs that make it to customers are much more serious and costly to resolve.

$\endgroup$
11
  • 2
    $\begingroup$ Modern x86 CPUs support microcode updates specifically because of the reason you mention: after being bitten by the FDIV and F00F bugs in P5 Pentium, P6 made it possible for microcode updates to change some things that weren't totally fixed-function. $\endgroup$ Sep 22, 2021 at 9:02
  • 2
    $\begingroup$ e.g. Skylake had several bugs, including some real-world bugs (not just theoretical code sequences nobody would ever run) that were worked around by disabling some parts of the hardware, leaving some performance pot-holes like branches in the last bytes of a 32-byte block because the microcode update disabled the uop cache (DSB) for such blocks, or disabling the loop buffer because of a partial-register merging corner case that went wrong with it enabled. en.wikichip.org/wiki/intel/microarchitectures/… $\endgroup$ Sep 22, 2021 at 9:04
  • 2
    $\begingroup$ But yes, updateable microcode can only do so much; there's still fixed hardware, and you have to consider things you're going to let microcode disable in case some future problem is found. Thus proper Meltdown mitigation required new CPUs or a software workaround; it was a whole new unanticipated class of vulnerability. And yeah, CPU vendors do extensive verification testing. (Intel got slack about that for Skylake -> more bugs than in past designs.) Related: danluu.com/cpu-bugs and zdnet.com/article/… $\endgroup$ Sep 22, 2021 at 9:10
  • $\begingroup$ Yeah, microcode just pushes it one level down. There's also FPGA, but it's not feasible to use them to implement a full CPU instruction set, so they're used for specialized co-processors. $\endgroup$
    – Barmar
    Sep 22, 2021 at 13:59
  • $\begingroup$ "pushes it one level down" - you're talking about traditional microcode like 6502 and Z80? And yes, in terms of answering this question, that's a great example; a simpler hard-wired CPU and a table of microcode. But Intel's "microcode" updates aren't just the Microcode Sequencer ROM contents (which gets used for some complex instructions like cpuid or lock cmpxchg). It also apparently can toggle controls for the state of how some logic blocks behave or interact, perhaps with something like an FPGA gate at a few key points designed ahead of time to have fallback modes of operation. $\endgroup$ Sep 22, 2021 at 14:35
4
$\begingroup$

If one can make the analogy, when would it break down? What features of language semantics (given by the interpreter), for example expressions and values, are there that we can't find at the physical level anymore? In what way does the processor behave differently from what is expected of an interpreter?

It's a bit of a semantic argument, but "language semantics" themselves don't exist at the physical level; there are physical states and transformations to which we assign a meaning.

You can generally find values in a processor all the way down to the bit level of individual transistors. However expressions get dematerialised. Instead you will find a set of enable and selector bits that route the values to a logic block which computes a function, then routes the result to a destination.

There are also processor features that don't map cleanly to language features. Out-of-order execution and speculative execution, for example. Speculative execution in particular is supposed to be entirely hidden from the programmer's model but in some circumstances has been used as a security exploit (SPECTRE).

Interrupts and aborts are also outside the simple machine code model, as they provide forced control flow transfer to a different bit of machine code.

$\endgroup$
2
  • $\begingroup$ OoO exec and pipelining in general are equivalent to the "as-if" rule: the code must execute as if each instruction was executed one at a time, in program order, before starting the next instruction. (Assuming a normal ISA, not a VLIW with explicit groups that execute in parallel like IA-64.) Maintaining this illusion is the cardinal rule of OoO exec. But just like in C and C++, the illusion is only maintained for the current core; other cores are allowed to see out memory operations appear out of order, unless barrier instructions (or the ISA's memory ordering rules) prevent it. $\endgroup$ Sep 22, 2021 at 9:43
  • $\begingroup$ (Some ISAs have restrictions on valid instruction sequences, e.g. ISAs with a branch-delay slot such as MIPS typically don't allow another branch in the delay slot: that causes unpredictable behaviour. Same for MIPS I with its load-delay slot: trying to read a load result in the next instruction would expose your code to the microarchitectural effects, e.g. reading the old reg value on a cache hit, else on cache miss it would stall and the next instruction would read the load result. MIPS I was only implemented on simple in-order pipelines; later MIPS had interlocks to stall there.) $\endgroup$ Sep 22, 2021 at 9:45
4
$\begingroup$

If you look too much at words, they'll scurry away. In general the boundaries on meanings of words are soft.

As others said, you are not wrong. But, the word interpreter is usually used precisely to mean "not the CPU".

How does an interpreter effectively carry out its interpretation? What is it interpreting on? (Or into?)

As the word is customary used, an interpreter is a bunch of instructions carrying out some other bunch of instructions (the program), but the effective execution of the interpreter code is done by something else (the CPU).

I do not know the details of CPUs inner workings, but at some point (say, after microcode translation) "instructions" turn into activation of different parts of the CPU, data turns into state of internal registers, some circuits are activated, producing (physical) internal states transitions, some internal communication lines (buses) are activated or disabled, states are moved from one register to another or to memory, [much more complicated real stuff omitted], and that's execution.

$\endgroup$
4
$\begingroup$

You can build any program as a circuit, check e.g. most texts on computability, they often discuss circuit complexity for solving problems in addition to the more traditional Turing machine models (closer to normal programs). For some problems it makes economic/performance sense to create a custom circuit (look e.g. at FPLGA), most of the time it is much cheaper/flexible to just write a program for a more or less general purpose CPU.

If your CPU is build as a fixed circuit, is a microprogram for a more basic CPU, programmed into a FPLGA, or as a program running on some CPU is really irrelevant. All are doing the job of interpreting the instructions.

$\endgroup$
3
$\begingroup$

TLDNR: No, not wrong.

The words we use are part of communication: you think - you say - I hear - I interpret. Depending on the context the word "interpreter" may be understood quite differently. So be careful when talking and writing, we do have different bakgrunds and different ways of interpreting words.

In my world, an interpreter is most often a software program so I could become confused. But let´s dive a little deeper.

.1 Executing the machine code: Yes the hardware fetches bits from memory and "interprets" them as code and then does what the code says, perhaps multiplying the values in two registers. A software interpreter would do the same. The hardware does some extra things a "pure" software cannot really do, such as consuming power from the power source and creating intended and unintended signals and electrical noise. It is not unusual for hardware designers to experience bugs due to these unintended things, especially in the edge case of supply voltages or temperatures.

NOTE: both hardware and software interpreters may container bugs of course, but that is a different story...

.2 Executing the machine code in detail: You might know of the Intel CPU-s used in a lot of computers, say the 10th generation i9. This computer executes x86 instructions (I am simplifying here, but bare with me). The x86 instructions are actually "translated" and "reordered" inside the i9 CPU before actually beeing executed. This translation process, from one assembly language to the interna language of the processor may be seen as an interpreter if you wish. The reason for the complicated multistage pipeline with translation and reordering is in order to gain performance.

.3 Conclusion: No, you are not wrong to see the hardware as an interpreter. But beware that this is not the common language usage, so you may end up confusing the listener or reader. I would stay away from using words that way, but that is me.

$\endgroup$
1
  • $\begingroup$ Most common x86 instructions decode to a single micro-op (but yes some are 2 or 3, and a few rare ones are a lot more). These uops then go through the rest of the superscalar OoO exec pipeline just like in an equivalent AArch64 or MIPS R10k or something, with reordering of exec happening just based on the availability of inputs (to hide latency e.g. cache misses) lighterra.com/papers/modernmicroprocessors and realworldtech.com/sandy-bridge. If you want a CPU that really "interprets" by running different micro-programs for each opcode, look at 6502 or Z80, or 8086. $\endgroup$ Sep 22, 2021 at 9:50
3
$\begingroup$

You can call everything everything - in 2021, all of our components (CPUs, machine code, compilers, interpreters) share so many aspects, that you'll find an argument in almost any direction. Maybe it would not be quite wrong to call a CPU an interpreter, but I feel it would be very weird and discount what actual interpreters are about in the first place.

An all-purpose CPU stupidly executes its instructions. If we ignore advanced current-days aspects of lookahead and heavy parallelization - i.e., think of an old, extremely simple, 6502 CPU instead of a current Intel or ARM offering - then you see that the CPU looks at one specific point in RAM or ROM, fetches one instruction, then executes that extremely simple instruction. There is nothing between this execution and the electrons running around on the hardware - at this low level, the machine code is the electronic layer.

So, no, in general I would say the processor is an executor, not an interpreter.

Modern aspects could change this. For example, you could create a CPU which understands CISC commands, but does this by running a microcode preprocessor inside the CPU which translates those CISC commands into RISC commands, which then are executed on the actual machinery of the CPU. In this case you could say the the CPU interprets CISC code. I would accept this especially in the case that this preprocessor has larger state than just the next command; i.e. if it does complex decisions based on previous and next statements. This also leads to branch prediction, parallelization, power management and so on - complex "management" efforts which may be reordering or optimizing the stream of incoming machine commands. This "preprocessor" then would be an interpreter, shoveling commands to its internal execution engine.

An actual interpreter earns its designation by looping over some more abstract representation of a program (sometimes this can be the source code directly, for example in certain scripting languages close to a shell; sometimes bytecode which can be generated upfront (e.g. Java) or on the fly (e.g. Ruby, Perl)). A common theme is that this bytecode is often compatible between different interpreters; famously you can run Java bytecode anywhere from big servers to embedded little machines, which may have nothing much in common on the machine language level.

Finally, all of this is a moving target anyway, since on each level of abstraction, we are combining all kinds of techniques. Your Java interpreter might have a Just-in-time compiler and your pieces of "bytecode" might in fact just be a compiled-in-the-meantime machine code. Your state-of-the-art CPU might have an interpretion layer for compatibility for some generation of CPU 20 years ago. Your compiler might have a compile-time interpreter able to modify compilation in some way, etc.

$\endgroup$
10
  • 2
    $\begingroup$ You mean "interprets CISC"? $\endgroup$
    – JDługosz
    Sep 20, 2021 at 15:21
  • 2
    $\begingroup$ I disagree with your first sentence - surely we cannot call a CPU a compiler. Yes, there's hardly any difference (or rather, a foggy line) between an executor and an interpreter. The latter often contains a preprocesssor or compiler, but it isn't one. $\endgroup$
    – Bergi
    Sep 20, 2021 at 18:32
  • 1
    $\begingroup$ I've strategically injected a word "almost" in that sentence, @Bergi. --- Yes, thanks JDługosz. $\endgroup$
    – AnoE
    Sep 21, 2021 at 7:07
  • $\begingroup$ @Bergi: Most CPUs aren't compilers, but Transmeta Crusoe basically was: dynamic recompilation to an internal VLIW, caching those optimized "compilation" results of their "Code Morphing Software". en.wikipedia.org/wiki/Transmeta_Crusoe. (And before anyone mentions it, this is very different from how modern Intel/AMD decode x86 instructions to one (or sometimes more) micro-ops to run through the rest of the superscalar OoO exec pipeline, even with SnB or Zen's uop cache (realworldtech.com/sandy-bridge) or even P4's trace cache.) $\endgroup$ Sep 22, 2021 at 9:15
  • $\begingroup$ @PeterCordes I maintain the distinction that the Transmeta Crusoe was not a compiler - it did contain a compiler. Next to all the other stuff like the execution unit. Together, all these parts compose an interpreter (for x86, for Java, or other ISAs). $\endgroup$
    – Bergi
    Sep 22, 2021 at 10:33
-1
$\begingroup$

If the hardware alone can interpret anything, yes. But with modern electronic digital data-processing the software is separate from the hardware. Even the BIOS or UEFI uses code.

In the mid-Twentiethh Century, the programmer actually rearranged the memory. So the memory was the program. There was no storage, per se. That was WHEN the Chairman of IBM speculated, given time, it might be possible to build a computer that weighed under 5 tons!

Given that he also predicted the world market might reach 8, eight computers in the entire world that is, he was a little off! So, if you have no code in the BIOS cmos memory, nothing stored on anything, just hardware and electricity, and 'that' can interpret; the answer to your question is 'yes'.

Otherwise, it is 'no'.

$\endgroup$
6
  • 6
    $\begingroup$ "In the mid-Ninteenth Century" ... is when the American Civil War took place, almost a century before computers were invented. $\endgroup$ Sep 20, 2021 at 9:22
  • 1
    $\begingroup$ It was when a member of nobility died who became famous for musing about human flight and the use of computing machinery beyond number crunching. $\endgroup$
    – greybeard
    Sep 21, 2021 at 5:49
  • 2
    $\begingroup$ In addition to having the wrong century, the limitations on computers that you speak about only apply to the ENIAC, which wasn't quite general purpose. The anecdote about Thomas Watson and the market for computers seems to be a myth and you also seem to be attributing to him a misquoted version of a much-reproduced 1949 Popular Mechanics quote ("Where a calculator like ENIAC today is equipped with 18,000 vacuum tubes and weighs 30 tons, computers in the future may have only 1000 vacuum tubes and perhaps weigh only 1½ tons.") $\endgroup$ Sep 21, 2021 at 14:11
  • $\begingroup$ The BIOS (or UEFI firmware) is not part of the CPU / processor. Firmware is just software that comes with the system, and runs when it first boots. Having some firmware on a ROM on the motherboard is a fundamentally different thing from how the CPU fetches, decodes, and executes instructions (whether it's from that ROM, or more code from RAM loaded there directly or indirectly by the firmware). $\endgroup$ Sep 22, 2021 at 9:36
  • $\begingroup$ I get where're you're going at: You want to tell me that for my bit of machine code to be run, the processor needs additional code that tells it what to do with my code. $\endgroup$ Sep 22, 2021 at 22:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.