The idea: many simple instructions or a few complex ones

An instruction set is the list of instructions a processor understands. A RISC design (reduced instruction set computer: MIPS, ARM, RISC-V) keeps every instruction simple and the same size. A CISC design (complex instruction set computer: x86) lets one instruction do several things, such as read memory, add and write back. The page compiles the same C line for both and runs it.

The C line a[i] += b at the top. Left: five MIPS instructions, sll, addu, lw, addu and sw, each a 4-byte word, 20 bytes in all. Right: one x86-64 instruction, add DWORD PTR [rdi+rsi*4], edx, 3 bytes: 01 14 B7. Under it, the three micro-ops the x86 core runs: load, add, store
The same line is 20 bytes of MIPS or 3 bytes of x86, but inside the x86 core it still becomes a load, an add and a store.

The values are fixed so every run is the same: a = 0x1000, i = 3, b = 5, and a[3] starts at 40. The arguments arrive in registers, as the calling conventions say: $a0–$a2 on MIPS, rdi, rsi, edx on x86-64 Linux.

Load/store vs memory operands

MIPS is a load/store architecture: only lw and sw touch memory, and arithmetic works on registers only. So a[i] += b needs five steps: shift i left by 2 (×4 bytes), add the base address, load, add b, store (Demo 1: a[i] += b).

x86 allows a memory operand with a scaled-index address: [rdi+rsi*4] means base + index × 4. One instruction, add DWORD PTR [rdi+rsi*4], edx, does the whole line. See how MIPS encodes loads, stores and array access in From C to MIPS Machine Code.

C lineMIPS32x86-64
a[i] += b;5 instructions, 20 bytes1 instruction, 3 bytes, 3 µops
x = y + z;1 instruction (addu), 4 bytes1 instruction (lea), 3 bytes, 1 µop
n = 100000;2 instructions (lui, ori), 8 bytes1 instruction (mov), 5 bytes, 1 µop
all three8 instructions, 32 bytes, 8 operations3 instructions, 11 bytes, 5 µops

CISC does not always win the count. x = y + z is one instruction on both (Demo 2). MIPS has three register fields, so the result can go to a third register. A plain x86 add overwrites one of its operands, so compilers borrow lea, the address-calculation instruction, as a three-operand add.

Fixed vs variable length decoding

Every MIPS instruction is one 32-bit word. The opcode is always bits 31–26, the register fields always sit at the same bits, and the next instruction always starts 4 bytes later. A decoder can split the word into fields with plain wires.

An x86 instruction is 1 to 15 bytes long. The decoder reads it byte by byte: optional prefixes, then the opcode, which says whether a ModRM byte follows; ModRM says whether a SIB byte and a displacement follow; the opcode also says how many immediate bytes follow. Only at the end does it know where the next instruction starts.

Top: the MIPS word 00054080 split into fixed fields op 0, rs 0, rt 5, rd 8, shamt 2, funct 0 at fixed bit positions. Bottom: the x86 bytes 01, 14, B7 read one after the other: 01 is the ADD opcode and says a ModRM byte follows, ModRM 14 says a SIB byte follows, SIB B7 gives rdi plus rsi times 4, so the length is 3
MIPS fields are found at fixed bit positions; x86 fields are found one byte at a time, each byte saying what comes next.

A 32-bit word leaves only 16 bits for a constant. 100000 (0x186A0) does not fit, so MIPS builds it with lui (upper half) and ori (lower half). x86 puts the 4-byte constant inside a 5-byte mov, low byte first (Demo 3: n = 100000).

Micro-ops: x86 is RISC inside

Since the Pentium Pro (1995), x86 cores do not execute complex instructions directly. The decoder cracks each one into micro-ops (µops), simple RISC-like operations. add [rdi+rsi*4], edx becomes load, add, store. The address rdi + rsi·4 is computed by the address unit of the load and the store, so it costs no extra µop: the core does 3 steps of work where MIPS spends 5 instructions.

Real Intel cores split the store again into store-address and store-data, so this instruction is 4 µops in the execution units and 2 in the front end (fused). The µops then flow through the same machinery as on a RISC core: register renaming and out-of-order execution, as in Out-of-Order Execution, and a pipeline, as in The MIPS Pipeline.

The trade-off

RISC (MIPS, ARM, RISC-V)CISC (x86)
instruction sizefixed, 4 bytes1–15 bytes
memory accessloads and stores onlymost instructions may use memory
code sizelargersmaller: more fits in the instruction cache
decodersimple, easy to decode many per cyclecomplex length decoding, power hungry
registers32 general-purpose16 general-purpose (x86-64)
compilermore instructions, simple choicesfewer instructions, many ways to say one thing

In the 1980s, memory was small and slow, so dense CISC code mattered. RISC bet that simple instructions could be pipelined and run at one per cycle. Today both sides borrowed from each other: x86 cores have RISC-like µop engines and a µop cache that skips the hard decoding for hot loops; ARM64 added scaled-index loads like ldr w8, [x0, x1, lsl #2], and RISC-V and ARM offer 2-byte compressed instructions (RVC, Thumb) to shrink code. See where the instruction set sits between the compiler and the hardware in Levels of Abstraction and how code is produced in Compiler Pipeline.

What the page leaves out

Clock cycles and timing (the steps on the page are not cycles), pipelining, superscalar issue and register renaming, the MIPS branch delay slot and the return jr $ra, x86 prefixes (REX, operand size, LOCK), the µop cache and macro-fusion, microcode for very complex instructions like rep movsb, the instruction cache, and RISC-V and ARM64 encodings.

On the mind map

This page on the Computer Architecture mind map · 35 pages in 7 branches · open it to see the whole map and test yourself in recall mode.