4 ms·
How is it possible that a RISC ISA can be nice to program for in Assembly? Wasn't PPC horrible for this for example? Wasn't the point of CISC to make it easier
by bni 6y ago
How is it possible that a RISC ISA can be nice to program for in Assembly? Wasn't PPC horrible for this for example?
Wasn't the point of CISC to make it easier for Assembly programmers (made sense when x86 and 68k was defined)
- socialdemocrat 6y agoI started with 68k on Amiga which made me love assembly. Then got exposed to x86 which I hated with a passion. Keep in mind I was quite young then and x86 had so many oddities and inconsistencies that it made it really hard for a beginner. In Uni when making a compiler I choose to target PPC as I figured anything was better than x86. I kind of regretted it. I was new to RISC and the heavy use of registers threw me off. E.g. using registers for all function arguments except when there where too many. Using a register for return address but then needing to use stack anyway of call stack got too deep. How every address had to be loaded in two steps. On top of that PPC did not offer a smaller and simpler instruction set. It was quite large from what I remember. So getting something akin to feeling like 68k was a dream that got popped. But I would say RISC-V gives me a bit of the 68k feeling as things are kept really small and beginner friendly.
- adrian_b 6y agoMost RISC ISA's, including PPC and ARM are much nicer to program in assembly than the Intel/AMD x86 ISA. The only exception is with RISC ISA's that are far too simple, e.g. the base RISC-V, so they lack many common instructions or addressing modes, forcing the programmer to use sequences of instructions instead of the single instructions of other, more complete, ISA's. Most RISC ISA's are relatively orthogonal, in the sense that you have to memorize only a small list of things, e.g. of kinds of instructions, kinds of registers, kinds of addressing modes, and then you can express any program as a combination of those few elements. On the other hand, for the Intel/AMD x86 ISA, to be able to write an optimized program, you need to know a huge list of things. The original x86 registers are all different having different features, there are not even 2 identical registers, so to find the optimal register allocation is difficult. Even the extra 8 registers added by the AMD 64-bit extension are not identical, but they are divided in 3 or 4 groups with different properties regarding the encoding of the instructions, which result in different program izes. Among the registers added by more recent ISA extensions, especially the SIMD extensions, SSE/AVX, there are finally groups of identical registers that are easier to allocate, but these must be used together with the integer registers, which are needed at least for addressing. It is difficult to determine the total number of different instructions in the x86 ISA, but they are much more than a thousand, many of which are obsolete and which should be avoided. Even when compared to older normal ISA's, which are not so complex like x86, e.g. Motorola 68k or IBM mainframes, many RISC ISA's, including POWER & ARMv8, are still an easier target for assembly programming, when you attempt to write an optimized program. When the performance of the program was not important, assembly programs for some traditional CISC ISA's e.g. Motorola 68k or DEC VAX could be simpler than for RISC ISA's, due to using fewer more complex instructions, but those instructions typically had slower implementations, so an optimized program might have been forced to avoid them. Knowing the very variable timing of the CISC instructions and accounting for that in order to write an optimized program, made optimized assembly programming more difficult than for RISC CPUs.
- userbinator 6y agoMy experience is pretty much the exact opposite, and I've been writing x86 Asm since the DOS days, only looking at ARM and other RISC stuff later. Most RISC ISA's are relatively orthogonal, in the sense that you have to memorize only a small list of things, e.g. of kinds of instructions, kinds of registers, kinds of addressing modes, and then you can express any program as a combination of those few elements. x86 is very orthogonal and has been since the 386. There's something called a ModRM, and the majority of the instructions use that form. The encoding is based on octal: https://gist.github.com/seanjensengrey/f971c20d05d4d0efc0781f2f3c0353da https://gist.github.com/seanjensengrey/f971c20d05d4d0efc0781... The original x86 registers are all different having different features, there are not even 2 identical registers, so to find the optimal register allocation is difficult. On the contrary, that guides register allocation. Too bad most compilers don't seem to know, which is why they are often very easy to beat (and why compiler output looks so distinctively different from good handwritten Asm.) Even the extra 8 registers added by the AMD 64-bit extension are not identical, but they are divided in 3 or 4 groups with different properties regarding the encoding of the instructions, which result in different program izes. I have no idea what you mean by "divided in 3 or 4 groups". The "high registers" are all accessed with an extra prefix byte. It is difficult to determine the total number of different instructions in the x86 ISA, but they are much more than a thousand, many of which are obsolete and which should be avoided. FUD, no one really cares about "total number of different instructions". If you think of the typical RISC with fixed 32-bit instructions, that's over 4 billion values... RISC is so bland and boring that it's hard to do a better job than a stupid compiler. An "op mem, reg" which is usually 2 or 3 bytes on x86 turns into at least 3 instructions (=12 bytes) and an explicit register allocation on a RISC. It's like writing microcode. No wonder they have so many registers --- they're really what a more intelligent CISC would use dynamically allocate internally in its uop execution engine/register renamer, saving cache occupancy and fetch bandwidth.
- adrian_b 6y ago"On the contrary, that guides register allocation" I agree that you are right that for simple programs you can use the x86 registers for the purpose chosen by Intel, e.g. CX for storing a loop counter and so on. Nevertheless, in my experience that are a lot of programs where you also want to use the registers for other things and if you would want to ensure that the program has the minimal size possible with the x86 encoding, you would have to move that variable from one register to another many times, to be able to use the shorter instructions possible with certain registers. Of course, you can just ignore a large number of the 8086 special instruction encodings that were designed to enable shorter programs, in which case you can use most registers in an almost orthogonal way. However, that is not very satisfying, to waste the extra existing hardware, just because it is hard to use. I prefer a CPU which does not implement features with little benefits, but if the features have already been implemented, I will rather use them. "The "high registers" are all accessed with an extra prefix byte." This is how it should have been, except that AMD was super lazy for unknown reasons and they saved a few decoding gates in a 64-bit CPU with millions of gates by not fully-decoding that extra prefix byte. Because of that, there are addressing modes where you cannot encode R12 and other addressing modes where you cannot encode R13. When using R12 or R13, certain instructions are longer than when using other registers and those instructions are not the same for R12 and for R13. So, to write the minimum-length program you must allocate differently R12, R13 and the other high registers. Moreover, there are other differences in the high registers that are not enforced by hardware, but they are enforced by the AMD64 ABI conventions about register usage, further dividing the high registers into groups with different properties. Also the high number of registers in RISC CPUs vs. CISC CPUs has almost no relationship with the RISC concept. One or two extra registers in a RISC are enough to cover the fact that a CISC instruction that combines a load with an operation uses an implicit register, besides the architectural registers. The fact that most RISC ISAs have more registers than older ISAs, which happened to be CISC, is due to the need for higher performance in modern CPUs. When you have more registers, you can interleave more chains of dependent operations, being thus able to hide the latencies of various execution units or to fully use all the execution units that would have stayed idle otherwise. Too many registers can lower the performance, due to the need for saving and restoring them, but 32 registers are definitely better than 16, because they frequently enable faster programs. Register renaming does not help with this. Register renaming eliminates the problem of shared resources (i.e. shared registers) in concurrent instructions, but it does not enable you to write a program that will hide the latencies caused by dependencies between instructions or that will be able to fully use all the execution units.
- mhh__ 6y agoIgnoring that ARM isn't all that RISC-y anymore, CISC vs. RISC is basically a trade-off between density and the ease of widening execution.