13 ms·
How Many X86-64 Instructions Are There Anyway?
- hawkice 10y agoThere's something to be said about the gigantic number. The machine needs to direct itself to the location of the data, and those methods aren't interchangeable to the machine or to people, unless performance-irrelevant machine code becomes a major use case.
- TazeTSchnitzel 10y agoThis is just looking at it from an assembly language point of view. Isn't it even more complicated at the actual byte level? For example, are an instruction, and then the same instruction but with a width prefix, different?
- DSMan195276 10y agoI'm not sure I would say more complicated, but you're completely right things are bit different on the byte level. For example there are certain prefixes that can be added indefinitely. Because of that there is a maximum instruction length x86 CPUs will decode, which I believe is 15 bytes - no valid instructions will go over that without adding unneeded prefixes, but without such a maximum the instruction set is technically infinite in length. That said, as far as the CPU is concerned (And keep in mind, x86 CPUs are stupid complicated so none of what I'm about to describe would really tell you how a particular x86 executes a particular instruction. This would apply better to simpler CPUs) an instruction with multiple widths is generally treated the same way for all of the widths. It decodes the opcode identifier for the instruction, and then would go on the decode the width from a separate part of the instruction. (Though I mean, commonly simple CPUs don't even support multiple widths). The hardware that handles that would commonly be the same or very similar. Debating whether or not that makes them "different" is just matter of definitions I think. But at the end of the day they are generally treated very similarly. It's also worth noting that assembly langauge's aren't quite a one-to-one mapping. It's fairly common for the assembler to substitute an equivalent instruction for one you used in cases where it knows it is better, and it is also common that a instruction doesn't actually exist on the CPU, but the mnemonics for it exists for convenience. But this does mean that the assembly language can actually represent more instructions then the CPU actually has, meaning the 'byte level' version can in some ways be less complicated, depending on your POV. I think for x86 this likely doesn't really make much of a difference though because the number probably isn't extremely high.
- __s 10y agoSee: RISC-V not having a negate instruction, because it's encoded as SUB 0, $X. Similarly no bitwise-not because XOR -1, $X
- baobrien 10y agoAlso no explicit register move instruction, it's ADDI rd,rs1,0. NOP is ADDI x0,x0,0.
- throwaway91111 10y agoI believe the longest valid instruction is 17 bytes, but it's been years since I knew how to construct it.
- spc476 10y agoOn the Motorola 68000, the MOVE instruction is used to move data from one location (memory or a register) to another location (memory or register). The size of the move is encoded in the instruction (two bits, only three patterns are legal). The instruction will affect the flags (set the Zero and Negative flags, clear the Carry and Overflow flags) based on value moved, except if the destination is an address register, in which case, the flags are not affected (and only two of the four bit patterns for size are valid). In fact, Motorola defined two instructions because of this, MOVE and MOVEA (move to address register). So, is this really one instruction (since both follow basically the same pattern)? Two instructions (because one sets the flags, the other doesn't)? Five (size and flags)? Also, the invalid bits (for size) are used to indicate other instructions, so there's a bit of overlap in decoding instructions.
- jsnell 10y agoSee also: https://fgiesen.wordpress.com/2016/08/25/how-many-x86-instructions-are-there/ https://fgiesen.wordpress.com/2016/08/25/how-many-x86-instru...
- breck 10y agoGreat read, thanks! Followup question: what's the distribution of transistors per instruction? Taking your number that there are ~2k instructions in Haswell, and given that Haswell has ~1.4 billion transistors (http://www.anandtech.com/show/7003/the-haswell-review-intel-core-i74770k-i54560k-tested/5 http://www.anandtech.com/show/7003/the-haswell-review-intel-...), that means on average ~1 million transistors per instruction. My guess is the majority of transistors go to things like the cache, and then there is duplication across cores, so the number is clearly much lower than that, but do you have any sense of what it costs to add an instruction in terms of number of transistors?
- TazeTSchnitzel 10y agoSome instructions are microcoded, right? That would mean some have a much smaller transistor impact.
- pjc50 10y agoThis is not a useful metric, surely? As you say most of the die is cache. What an instruction costs depends mostly on what you want to do, and how many bits wide it is. Multipliers are expensive. Then there's considerations of pipeline depth and branch prediction.
- deepnotderp 10y agoThe vast majority of instructions are microcoded, so it's unlikely to be much at all, instead you're killing the poor decoder :P In any case, the primary energy and die space hogs are the OoO circuitry and the caches.
- astrodust 10y agoProbably zero. The decoder isn't instruction specific, it's just something that translates the incoming ops into micro-ops internally. Even then it's pretty abstract. Is an adder circuit specific to an add operation? It's probably used for a lot of things.
- dom0 10y ago> but do you have any sense of what it costs to add an instruction in terms of number of transistors? There is no answer to this question. It does not make sense in the domain of a modern microprocessor. ("It does not compute").
- aviraldg 10y agoIn the undergraduate level computer architecture class I just finished, it was pretty much stated as fact that the simpler design and fixed instruction format of RISC based architectures makes them much more suitable for pipelining, and hence leads to better performance than those based on CISC. Why are x86/64 processors used for most high performance applications then?
- adamnemecek 10y ago> Why are x86/64 processors used for most high performance applications then? Modern Intel cpus are actually risc under the hood. https://en.m.wikipedia.org/wiki/Microcode https://en.m.wikipedia.org/wiki/Microcode
- beached_whale 10y agoI have a naive understanding, but the compilers had to do a lot more work with the RISC systems. Also, is anything really your classic RISC any longer? Lots of new instructions and instructions that take a lot longer than 1 cycle are there. Anecdotally when looking at the assembly for Intel or Arm, they are often very close.
- wolfgke 10y ago> Anecdotally when looking at the assembly for Intel or Arm, they are often very close. First: Modern ARM chips (i.e. what you will typically find in a mobile phone) support three instruction sets: A32, T32 (Thumb-2 on modern ARM chips) and A64 (if you don't know what they mean, google it up). So it hardly makes sense to talk of "ARM assembly" if you don't specify which instruction set you mean. I know there is UAL, which in some sense unifies the instructions of A32 and T32 on assembly level. There are very central differences that you will observe when looking at the disassembly of all ARM instruction sets vs. x86-32 or x86-64. - Typical x86 ALU instructions have 2 operands. Typical ARM ALU instruction will have 3. This is very typical for CISC vs. RISC instruction sets. Side note: A compiler often does register allocation by graph coloring. If 3-operand instructions are used this is an NP-hard problem. On the other hand if 2-operand instructions are used, we obtain a chordal graph, for which the graph coloring problem can be solved in polynomial time: https://en.wikipedia.org/w/index.php?title=Chordal_graph&oldid=777964476 https://en.wikipedia.org/w/index.php?title=Chordal_graph&old... - x86 ALU instructions also accept a memory both as source and destination (side note: if we add a register to the value at a memory address, on modern x86 cores this is mapped to 3 mu ops: load value, add, storeobly value). On the other hand (typical for RISC) ARM is a load-store architecture. So ALU instructions don't accept memory address contents as operands - instead one has to load the content of the address into a register first, do the ALU instruction and use a store instruction to store the result in memory. Side note: On x86 "{alu_instruction} r/m, r" (e.g. add [edx], eax) is atomic with respect to interrupts, e.g. when an interrupt occurs either this instruction has been executed completely or not at all. You want to make it also atomic with respect to code executing on other cores? Just add a LOCK prefix. - Even in 32 bit mode ARM already offers many registers (16 GPRs) and in A64 even 32. x86-32 only offers 8 and x86-64 16. Having more and orthogonal registers is typical for RISC vs. CISC. Thus ARM's call convention uses registers for passing the parameters (again very typical for RISC) and uses a link register for passing the return address. x86-32 instead typically passes return address and parameters on the stack (I know that under 32 bit Windows there also exists the __fastcall call convention that uses registers for passing parameters, too. But this is an exception). But admitted: under x86-64 on the Linux and Windows call convention they also use registers for passing parameters. - At least A32 and T32 cannot directly call functions that are too far away from the current instruction. So the linker has to insert veneers, which make this possible. One of course will not find veneers on x86. - It is not easy to access memory addresses relative to the instruction pointer on x86-32 (under x86-64 it is easily possible), while on ARM it is. So ARM assembly code will often contain small const variable values next to the function. One hardly sees such code on x86-32 (though on x86 it is not really necessary, since there are instructions that put some arbitrary constant into a register; A32 and T32 on the other hand allow only to encode some kind of constants, bases on a rather complicated scheme that I will not explain here; so this trick is rather helpful for writing ARM code). TLDR: Better look again at the disassembly carefully.
- gwu78 10y agoThe knee-jerk answer upon seeing the title was: "Too many". So many of these instructions I never see anyone use, ever. No doubt there are some folks using them, but as mere mortals, do the rest of us really need all these features to control our small amount of commodity hardware? As a user, I have modest goals. Is it not true that Torvalds wrote his kernel with a similarly modest goal in mind: control over his own commodity computer? The situation resembles that of an overcomplex software program where a majority of the features are unused by an even larger majority of its users. In other words the depth of features benefit only the very few people who use them. Given the choice between several alternatives with differing levels of features I tend to opt for software that is less featureful and hence more simple. Call me simple-minded if you wish. The same goes for processors, although when it comes to hardware how much choice to we really have as end users? (Hobbyist boards excluded.) For a taste of some non-x86 assmbler, I enjoyed experimenting with a MIPS simulator still found at spimsimulator.sourceforge.net. I can report that the non-GUI portion at least still compiles relatively cleanly on BSD. This simulator has been mentioned on HN several times. I have a no problem with using a processor with fewer instructions even if I have to sacrafice something by making that choice -- I leave it to the experts to detail those sacrafices and why I would be a fool to make them. NB: I am already a fool so it may not be worth the effort. How many HN readers have tried RISC-V? A poll for those who have not: will RISC-V inspire you to purchase a new computer?
- dom0 10y agoPrediction: RISC-V will at best take on in some niche markets. If RISC-V is lucky, it will maybe displace MIPS. -- Usual P.S.: The ISA has become less and less relevant to processor performance since the mid 90s (when Intel and AMD introduced micro-ops to the x86 world by dynamic translation) and is now less relevant than ever before. What is relevant is developer mindshare, good compilers, availability of optimized algorithms, and manufacturers pouring billions into creating better scheduling and execution for µops.
- madez 10y agoThe performance is not the relevant part. If it's fast enough, it's enough. Then other things matter. For me, that "then" is already reached.
- Marat_Dukhan 10y agoI made a Python package which documents x86(-64) instructions in a ready-to-use way: https://github.com/Maratyszcza/Opcodes https://github.com/Maratyszcza/Opcodes (also `opcodes` on PyPI). With this package, its easy to collect ISA stats, e.g. import opcodes.x86_64 isa = opcodes.x86_64.read_instruction_set() print(sum(len(instruction.forms) for instruction in isa)) >>> 6020 As an another example, here is number of instruction forms (e.g. mnemonic name + operand types) over time on Intel CPUs: http://imgur.com/a/AVPcq http://imgur.com/a/AVPcq
- deleted 10y ago[deleted]
- kccqzy 10y agoMaybe I should add that sometimes very different instructions get assigned to the same mnemonic. Like the venerable mov. Moving data from typical general purpose registers is very different from moving data to and from debug registers and control registers, and have different opcodes, yet they have the same mnemonic. You won't find them in typical programs because they need Ring 0.
- jcranmer 10y agoLLVM's answer to this question is about 14,600. This comes from treating memory and registers operands as different (i.e., add %rax,%rbx and add %rax,(%rbx) are two different instructions, although note that add %rax,%fs:16(%rbx,%rdi,4) is counted as the same instruction as add %rax,(%rbx)). I will also point out that LLVM's list is not exhaustive--it's definitely missing a few operand types for a few instructions (e.g., nop %rax).
- partycoder 10y agoThe Intel architecture manufacturers privilege reverse compatibility, so I am not sure if there's a limit where it would be good to sacrifice some of that compatibility in exchange for performance or simplicity. I mean, for example I have not seen a single person talking about how to integrate AMD's 3DNow! in their software. Mostly because AMD adopted SSE, but Intel didn't adopt 3DNow!, so people use SSE... as a simple example. So you end up with a vestigial set of unused instructions... with the associated cost, since it's not for free in terms of design, implementation, manufacturing, etc.
- wolfgke 10y ago> I mean, for example I have not seen a single person talking about how to integrate AMD's 3DNow! in their software. Mostly because AMD adopted SSE, but Intel didn't adopt 3DNow!, so people use SSE... as a simple example. So you end up with a vestigial set of unused instructions... with the associated cost, since it's not for free in terms of design, implementation, manufacturing, etc. Because of this reason AMD decided to drop support for 3DNow! in more recent processors: > https://en.wikipedia.org/w/index.php?title=3DNow!&oldid=769683777 https://en.wikipedia.org/w/index.php?title=3DNow!&oldid=7696... "However, the instruction set never gained much popularity, and AMD announced on August 2010 that support for 3DNow would be dropped in future AMD processors, except for two instructions (the PREFETCH and PREFETCHW instructions). The two instructions are also available in Bay-Trail Intel processors.". Also look under "Processors supporting 3DNow" (emphasis mine): "All AMD processors after K6-2 based on K6, Athlon, Athlon 64 and Phenom architecture families. Not supported in Bulldozer, Bobcat and Zen architecture processors and their derivates."
- partycoder 10y agoI see!, thanks for pointing out this about 3dNow!.
- combatentropy 10y agoHow many instructions do RISC architectures have?
- segmondy 10y agoIt's strange to me that they are counting asm instructions, I would count at the opcode level since multiple asm can be synthetic.
- aswanson 10y agoNobody knew software could be so complicated. Seriously, though, the world would be a better place if Motorola would have evolved the 68000 architecture to win the pc market.
- deepnotderp 10y agoI quite like RISC-V , it's simple, elegant and efficient. Undergraduate students can quite easily put together competitive in order cores. That itself is a testament to it. No wonder, considering Patterson and Hennessey literally wrote the book on computer architecture!
- oldandtired 10y agoIEEE Spectrum in the early 80's had an article on minimal instruction sets. The author made a salient point that 7 instructions did most of the heavy lifting, another 7 did the most of the rest required. He did highlight that one mistake made with instruction sets was not separating the addressing modes from the instruction itself. There have also been various projects looking at the micro-instruction based machines and noting that extremely complex instruction sets could be designed so that the actual requirements of a programmer or project be placed in microcode. One example was an instruction to search a tree structure for a required value (as a single machine instruction). Not that I can do anything about it, my conclusion over nearly 4 decades is that we have failed to take advantage of the increasingly denser silicon to make higher level machines, in particular machines that recognise the difference an instruction and a data element. We can write very high level software languages but all have to be run on extremely low level hardware. Too much commodity and not enough variability.
- adyavanapalli 10y agoCan you please link that article?
- oldandtired 10y agoSee my comment above.
- djsumdog 10y agoAre you talking about Very Long Instruction Words (VLIW)? IIRC, that's the concept of having the scheduling done in the compiler. Instead of the compiler spitting out op codes and operands, each part of the instruction space controls specific functional units. So if you stick something in the adder, the documentation might specify the next x instructions need to be nops so it can complete. The idea being if scheduling is done at compile time, you can update the compiler and update the scheduling/performance. Unfortunately, creating compilers for these systems was incredibly difficult, hence the failure of ix64/EPIC.
- 10y ago
- chadgeidel 10y agoForgive my ignorance, but I don't see a link to the actual "instr-count" program and I don't see a GitHub link anywhere. What does the program do? How does it divine the instruction count?
- desdiv 10y ago>All the numbers in this blog post have been obtained through a small program making use of our awesome C++11 library for working with x86-64 assembly. Just like the library, my program is available as open source on GitHub. https://github.com/stefanheule/x86_64-instruction-count https://github.com/stefanheule/x86_64-instruction-count
- chadgeidel 10y agoOh, goodness. Reading fail. Thank you!
- pslam 10y agoThis is the wrong way to go about it. x86 mnemonics bear little resemblance to the encoded binary machine code. For example, what x86 lumps into a single "mov" mnemonic, is actually half a dozen different underlying instructions, e.g load, store, reg-reg, and a few special cases. It's the wrong question too. Perhaps what you're looking for is: "What is the number of combinations in which an instruction can be decoded?" This would need to lump together all the multi-bit fields (such as immediates) as one (or a few if there's special values). This would be a measure of the expressivity of instruction set, and somewhat a measure of the encoding efficiency — how much it can cover the execution unit inputs? It's a much easier thing to answer for most of the "RISC" oriented architectures, e.g ARM 32 and 64 bit. It's basically the set of valid binary encodings of instructions, compressing together all the immediate values.
- Questron 10y agoAll the different instructions are listed in intel's instruction reference manuals. What is not very wise about this article is that he's using AT&T syntax. It adds one pointless level between the actual assembly and the programmer, and it has these syntax differences compared to reference manuals, which makes it frustrating to use (both read and write).
- Erwin 10y agoCuriosly the capability of the x86 MOV is such that you can compile C code to only MOV instructions: https://github.com/xoreaxeaxeax/movfuscator https://github.com/xoreaxeaxeax/movfuscator Inspired by this paper about Turing-completeness of MOV: http://www.cl.cam.ac.uk/~sd601/papers/mov.pdf http://www.cl.cam.ac.uk/~sd601/papers/mov.pdf
- euph0ria 10y agoHow many instructions does the average engineer that does low-level work know by heart and need to know to work effectively with it?
- glaberficken 10y agoAmateur/hobbyist programmer here. Is there a good bottom up explanation of computing that you know of? i.e. something that starts at the hardware level (how a CPU works) and then moves up through the abstractions layers until you get to a top level language like JS running inside a browser? I've been looking for something like this for a while, mainly to help explain computers to lay people that are interested in the details.
- wolfgke 10y agoFor a popular scientific view on this topic, I recommend Noam Nisan, Shimon Schocken - The Elements of Computing Systems: Building a Modern Computer from First Principles You can find the first half of the book at http://www.nand2tetris.org/course.php http://www.nand2tetris.org/course.php
- glaberficken 10y agoThanks! that surely looks interesting and I will check it out in more detail. However I was looking for something more summarized and using metaphors for the layman.
- wolfgke 10y agoIf you prefer a computer game over a book, have a look at MHRD: > http://store.steampowered.com/app/576030/MHRD/ http://store.steampowered.com/app/576030/MHRD/ This game is rather similar in spirit to "The Elements of Computing Systems", which I recommended above, but more summarized (though it only considers up to CPU level in opposite to the Nisan-Schocken book).
- glaberficken 10y agoThank you =) I will look into it
- tomerv 10y agoAny count based on mnemonics is off by 1 because of the CMPSD mnemonic. This mnemonic maps to both a string instruction and a SIMD (floating point) instruction. You probably want to count them separately. It's funny that this mnemonic is mentioned in the article, but the author didn't notice that it actually points to 2 families of instructions, not 1!