← tonia.ai
MCS 510 · Advanced Computer Architecture

Inside the instruction set

What an instruction set defines, how the major ISA families differ, and how designers trade encoding bits, hardware cost and software compatibility against the needs of a target application. Each part includes something to try, and the page ends with tools and papers for deeper study.

Part A

Anatomy of an instruction set

What an ISA specifies

An instruction set architecture is a specification, not a chip. It defines everything a program, compiler or operating system can observe about the processor, and leaves everything else (pipeline depth, cache sizes, predictor design) to the implementation. Amdahl, Blaauw and Brooks drew this line when designing the IBM System/360, and it is why the same binary can run on a phone core and a server core that share an ISA.

Programmer-visible stateGeneral-purpose and floating-point registers, program counter, status flags, control registers
Data typesInteger widths, signedness, IEEE 754 floating point, packed SIMD and vector element types
Instruction formatsInstruction length and how bits are divided into opcode, register and immediate fields
Addressing modesHow an instruction computes the memory address it reads or writes
OperationsData transfer, arithmetic and logic, control flow, floating point, vector, atomic, system
Memory modelByte order, alignment rules, and which load/store orderings other cores may observe
Privilege and exceptionsExecution modes, traps, interrupts, and the virtual-memory interface the OS programs

Calling conventions (which register holds the return address or the first argument) belong to the ABI, a software agreement layered on top of the ISA.

Registers and data

Registers are the fastest storage in the machine, and the ISA fixes how many a program can name. More registers mean fewer spills to memory, but each one costs encoding bits in every instruction that names it, plus register-file area, read ports and save/restore time on a context switch.

ISAInteger registersFP / vector registersNotes
x86-6416 × 64-bit16 or 32 (XMM/YMM/ZMM)Intel APX extends integer registers to 32
AArch6431 × 64-bit32 × 128-bitRegister 31 reads as zero or the stack pointer, depending on the instruction
RISC-V RV6432 × 64-bit32 FP, 32 vectorx0 is hardwired to zero; RV32E cuts to 16 for tiny cores
MIPS3232 × 32-bit32 FP$zero hardwired, the RISC convention RISC-V kept
MOS 6502A, X, Y (8-bit)noneAccumulator machine; zero page acts as extra registers

Byte order is part of the data definition. Storing the 32-bit word 0x12345678 at address 0x100 lays out bytes differently:

Address0x1000x1010x1020x103Used by
Little-endian78563412x86, RISC-V, Arm (in practice)
Big-endian12345678Network byte order, IBM z, SPARC, classic 68k

Instruction formats and encoding

Encoding decides how hard instructions are to fetch and decode. Fixed-length encodings (AArch64, RISC-V, MIPS: 4 bytes) let a wide core find instruction boundaries trivially and decode many instructions in parallel. Variable-length encodings (x86: 1 to 15 bytes) pack common operations into fewer bytes but force the decoder to find each instruction's length before it can start the next. A middle path adds a 16-bit compressed subset: Arm Thumb-2 and the RISC-V C extension.

RISC-V uses six 32-bit formats. Register specifiers always sit in the same bit positions, so the register file can be read before the decoder has finished working out what the instruction is. Immediates are split across fields so that the sign bit is always bit 31.

Format31–2524–2019–1514–1211–76–0Used for
Rfunct7rs2rs1funct3rdopcodeRegister–register ALU
Iimm[11:0]rs1funct3rdopcodeImmediate ALU, loads, jalr
Simm[11:5]rs2rs1funct3imm[4:0]opcodeStores
Bimm[12|10:5]rs2rs1funct3imm[4:1|11]opcodeConditional branches
Uimm[31:12]rdopcodelui, auipc
Jimm[20|10:1|11|19:12]rdopcodejal

Try the decoder

Enter a 32-bit RV32IM instruction in hex, or pick an example. The decoder splits it into fields and disassembles it.

add x3, x1, x2
ABI names: add gp, ra, sp · R-type

Addressing modes

An addressing mode is the recipe for the effective address. Rich modes let one instruction do the work of several; simple modes keep the pipeline short and regular. Studies of VAX programs in the early 1980s found that a few modes (register, immediate, displacement) covered the large majority of uses, a key argument for RISC.

ModeEffective addressExampleTypical use
ImmediateOperand is in the instructionaddi a0, a0, 8Constants
RegisterOperand is in a registeradd a0, a1, a2Arithmetic
Base + displacementReg + constantld a3, 16(sp)Locals, struct fields
Scaled indexBase + index × scale + dispmov rax, [rbx+rcx*8+16]Array elements (x86)
Register offsetBase + shifted registerldr x0, [x1, x2, lsl #3]Array elements (Arm)
Post-indexUse base, then base += nldr x3, [x0], #8Walking an array (Arm)
PC-relativePC + constantauipc a0, 0x2Position-independent code, branches
Memory indirectAddress read from memoryMOVL @(R1), R0Pointers (VAX); dropped by RISC

RISC-V has only base + 12-bit displacement for loads and stores. Everything else is built from extra instructions, which cores can fuse back together internally.

Operations and control flow

Instruction sets group operations into a handful of categories: data transfer (load, store, move), integer arithmetic and logic, control flow (branches, jumps, calls, returns), floating point, SIMD or vector, atomic memory operations, and system instructions (traps, fences, cache and TLB control).

Conditional branches come in two styles. Condition codes (x86 RFLAGS, Arm NZCV) are set as a side effect by arithmetic, and a later branch tests them. That saves an instruction but creates an implicit dependency on a single shared register that out-of-order hardware must rename. Compare-and-branch (RISC-V, MIPS) puts the comparison in the branch itself, so there is no hidden state, at the cost of encoding two register fields in every branch.

Atomics also split two ways. Load-reserved/store-conditional (RISC-V LR/SC, Arm LDXR/STXR) builds any read-modify-write from two simple instructions. Single atomic instructions (x86 lock cmpxchg, Arm LSE, RISC-V AMOs) perform the operation in one step and scale better under contention.

Privilege, exceptions and the memory model

ISAPrivilege levelsMemory ordering
x86-64Rings 0–3 (OS in 0, apps in 3), plus VMX root/non-root for virtualizationTSO: stores may be delayed past later loads; little else reorders
AArch64EL0 apps, EL1 kernel, EL2 hypervisor, EL3 secure monitorWeakly ordered; explicit barriers and acquire/release instructions
RISC-VU user, S supervisor, M machine; H extension for hypervisorsRVWMO (weak), with an optional Ztso extension for TSO

An exception is caused by the instruction itself (page fault, illegal instruction, system call); an interrupt comes from outside (timer, device). Modern ISAs require precise exceptions: when the handler runs, every earlier instruction has completed and no later one has changed visible state. Out-of-order cores pay for this with the reorder buffer.

The memory consistency model is the most subtle part of a multicore ISA. A weaker model gives hardware more freedom to reorder and buffer memory operations; a stronger model is easier to program. Binary translators such as Apple's Rosetta 2 must preserve x86 TSO behavior on weakly ordered Arm hardware, and Apple Silicon includes a hardware TSO mode for that reason.

Part B

Comparing instruction sets

Classes by where operands live

The oldest way to classify ISAs is by where an ALU instruction finds its operands. Here is C = A + B in each style:

StackAccumulatorRegister–memoryLoad–store
push A
push B
add
pop  C
load  A
add   B
store C
load R1, A
add  R3, R1, B
store R3, C
load R1, A
load R2, B
add  R3, R1, R2
store R3, C
JVM, WebAssembly, x87 FPU6502, early machines, many 8-bit MCUsx86, IBM System/360 and zRISC-V, Arm, MIPS, Power

Stack and accumulator code is compact because operands are implicit, which is why virtual ISAs like the JVM and WebAssembly use a stack: small downloads, easy verification. Load–store machines need more instructions, but every instruction is simple, registers are explicit, and the compiler can schedule freely. Since about 1980 nearly every new general-purpose ISA has been load–store.

CISC, RISC and beyond

CISC designs of the 1970s (VAX, x86, 68k) aimed to close the "semantic gap" with rich instructions and addressing modes, implemented with microcode. The RISC work at IBM (the 801), Berkeley and Stanford showed that compilers used a small subset of those instructions, and that a simple, pipelined load–store design with many registers ran faster. Since the Pentium Pro, x86 cores translate instructions into RISC-like micro-operations internally, so the old performance gap has largely closed.

VLIW (very long instruction word) moves scheduling from hardware to the compiler: each wide instruction bundles several independent operations that issue together. It succeeded in DSPs (TI C6000, Qualcomm Hexagon) where code is regular and power is tight, and struggled in general-purpose computing (Intel Itanium), where compilers cannot predict cache misses and branches well.

Packed SIMD (SSE, AVX, NEON) operates on fixed-width registers, so every widening (128 to 256 to 512 bits) adds a new set of instructions. Vector-length-agnostic ISAs (Arm SVE, RISC-V V) let one binary run on hardware with any vector width, reviving the approach of the Cray vector machines.

x86-64AArch64RISC-V RV64GC
StyleCISC, register–memoryRISC, load–storeRISC, load–store
Instruction length1–15 bytes4 bytes4 bytes, or 2 (C ext.)
ALU operands2, destructive (3 with VEX)33
Memory operands in ALU opsYesNoNo
BranchesFlags (RFLAGS)Flags (NZCV), plus cbz/cbnzCompare-and-branch
Load/store addressingBase + index×scale + disp, RIP-relativeOffset, register offset, pre/post-index, literalBase + 12-bit offset
SIMD / vectorSSE, AVX2, AVX-512, AMXNEON, SVE/SVE2, SMEV extension
ExtensibilityPrefix bytes added over decadesVersioned features (v8.x, v9.x)Modular base + lettered extensions; custom opcode space
LicensingProprietary (Intel, AMD)Licensed by ArmOpen, royalty-free

One function, three ISAs

The same array sum, written by hand for each ISA (arguments arrive in registers per each platform's ABI):

long sum(long *a, long n) {
    long s = 0;
    for (long i = 0; i < n; i++) s += a[i];
    return s;
}
x86-64
sum:
  xor   eax, eax
  test  rsi, rsi
  jle   .done
  lea   rdx, [rdi+rsi*8]
.loop:
  add   rax, [rdi]
  add   rdi, 8
  cmp   rdi, rdx
  jne   .loop
.done:
  ret
AArch64
sum:
  mov   x2, #0
  cmp   x1, #1
  b.lt  .done
.loop:
  ldr   x3, [x0], #8
  add   x2, x2, x3
  subs  x1, x1, #1
  b.ne  .loop
.done:
  mov   x0, x2
  ret
RISC-V RV64
sum:
  li    a2, 0
  blez  a1, .done
  slli  a1, a1, 3
  add   a1, a0, a1
.loop:
  ld    a3, 0(a0)
  add   a2, a2, a3
  addi  a0, a0, 8
  bne   a0, a1, .loop
.done:
  mv    a0, a2
  ret
ISAInstructionsLoop bodyCode sizeHighlighted feature
x86-649424 bytesMemory operand: load and add in one instruction
AArch649436 bytesPost-index load bumps the pointer for free
RV64G10440 bytesCompare-and-branch, no flags
RV64GC10424 bytes8 of 10 instructions compress to 2 bytes

Sizes measured by assembling these exact listings with LLVM. Each ISA reaches a four-instruction loop by a different route. Paste the C into Compiler Explorer to compare with compiler output at different optimization levels.

Performance implications

CPU time = Instruction count × CPI × Clock cycle time

The ISA touches all three terms. Richer instructions lower the instruction count. Simple, regular instructions lower CPI because they pipeline well and decode in parallel. Decode complexity can lengthen the critical path and raise the cycle time, or force extra pipeline stages that make branch mispredictions more expensive.

Modern implementations blur these effects. x86 cores cache decoded micro-ops to skip the expensive decoder on hot loops, and both x86 and RISC cores fuse common instruction pairs (compare + branch, lui + addi) into one internal operation. Blem, Menon and Sankaralingam measured ARM and x86 cores and found that the ISA itself had no significant effect on performance or energy; microarchitecture and design targets explained the differences.

Where the ISA still clearly matters:

  • Code density affects instruction-cache misses, fetch bandwidth, and flash cost in embedded parts.
  • Decode width. Fixed-length instructions make 8-wide decode practical; variable-length decode costs area and power.
  • Vector and matrix extensions give order-of-magnitude gains on the kernels they target.
  • Memory model. Weaker ordering allows more aggressive store buffering; stronger ordering simplifies concurrent software.
  • Ecosystem. Compilers, libraries and binary compatibility often outweigh any technical advantage.
Part C

Designing for an application

Design decisions and what they cost

DecisionGainCost
Fixed-length instructionsSimple, parallel decode; easy boundariesLower code density; wasted bits on simple ops
Variable-length or compressedSmaller code, fewer I-cache missesComplex fetch and decode; instructions can cross cache lines
More registersFewer spills, more room for compiler schedulingMore bits per operand; bigger register file; slower context switch
3-operand vs 2-operandNon-destructive; fewer copy instructionsOne more register field per instruction
Rich addressing modesFewer instructions for array and struct accessMore address-generation hardware; harder pipelining
Condition codesCompare is free after arithmeticImplicit dependency that must be renamed
Larger immediatesFewer instructions to build constants and offsetsFewer bits left for opcodes or registers
Specialized instructionsLarge speedups on target kernelsOpcode space, verification effort, unused silicon elsewhere
Backward compatibilityExisting software keeps runningLegacy features must be supported forever
Security featuresHardware-enforced memory safety or control-flow integrityExtra state, encoding space and software changes

The encoding budget

Every instruction has a fixed number of bits to share among the opcode, register specifiers and immediate. Adjust the design to see what fits.

10 bits left for function codes or immediate

Reading the result. The default, 32 registers with 3 operands and a 7-bit opcode, is RISC-V's R-type: 22 bits used, 10 left for funct3 and funct7. An I-type instruction drops one register field, which frees 5 bits and gives a 12-bit immediate.

Try a 16-bit instruction with 32 registers and 3 operands: it does not fit. Compressed encodings such as RISC-V C get around this by using 2 operands and limiting some fields to 8 popular registers (3 bits each).

Matching the ISA to the application

ApplicationWhat mattersISA choicesReal examples
Microcontrollers and IoTCode size, energy, gate count, interrupt latency16/32-bit mixed encoding, fewer registers, no MMU, simple pipelineArm Cortex-M (Thumb-2 only), RISC-V RV32EC/IMC
Digital signal processingMultiply-accumulate throughput, deterministic timingMAC, saturating and fixed-point math, zero-overhead loops, circular addressing, VLIWTI C6000, Qualcomm Hexagon, Cadence Tensilica, PULP RI5CY
Mobile application processorsPerformance per watt, large software ecosystemClean 64-bit RISC, SIMD, heterogeneous core supportAArch64 with big and little cores
Desktop and serverSingle-thread speed, binary compatibility, virtualizationWide SIMD, large memory addressing, hypervisor modesx86-64, Arm Neoverse
Machine learningDense matrix math at low precisionMatrix and tensor instructions; FP16, BF16, FP8, INT8 typesIntel AMX, Arm SME, Google TPU (a few coarse CISC-style instructions)
CryptographyThroughput and constant-time executionAES rounds, SHA steps, carry-less multiplyAES-NI, Arm crypto extensions, RISC-V Zk
Memory-safe systemsHardware-enforced bounds and permissionsCapabilities, pointer authentication, memory taggingCHERI (Arm Morello), Arm PAC and MTE
Portable code distributionCompactness, verifiability, any-host executionStack-based virtual ISA, translated by a JIT or ahead of timeWebAssembly, JVM bytecode

Worked example: should we add a multiply-accumulate?

A team building an audio processor finds that a dot-product kernel takes 60% of run time. On RV32IM the inner loop is 7 instructions:

Base RV32IM
loop:
  lw    t0, 0(a0)
  lw    t1, 0(a1)
  mul   t2, t0, t1
  add   a2, a2, t2
  addi  a0, a0, 4
  addi  a1, a1, 4
  bne   a0, a3, loop
With a MAC instruction
loop:
  lw    t0, 0(a0)
  lw    t1, 0(a1)
  mac   a2, t0, t1
  addi  a0, a0, 4
  addi  a1, a1, 4
  bne   a0, a3, loop

Benefit. The kernel drops from 7 to 6 instructions. If CPI is unchanged, Amdahl's law gives 1 / (0.4 + 0.6 × 6/7) = 1.094, about a 9% speedup.

Cost. mac reads three registers (two sources plus the accumulator), so the register file needs a third read port, and a multiplier feeding an adder lengthens the critical path. If that raises the cycle time by 3%, the net speedup is 1.094 / 1.03 = 1.062. Every other program pays the 3% too, with no benefit.

Alternatives. Post-increment loads would remove both addi instructions, and a hardware loop would remove the branch, bringing the loop to 3 instructions. The PULP project's RI5CY core added exactly this set (MAC, post-increment loads, hardware loops) to RISC-V for near-threshold IoT signal processing.

1.062× overall speedup
Bar centered on 1.0×; left is a slowdown, right is a speedup (range 0.5× to 2×).

Evaluating a proposed instruction

  1. Profile real workloads. Find where time goes and which instruction sequences repeat. A new instruction only helps code that uses it.
  2. Estimate the ceiling. Apply Amdahl's law and the iron law with optimistic assumptions. If the best case is small, stop here.
  3. Check the encoding. Count the opcode space and register fields it needs and whether it fits existing formats. Prefer reserved or custom opcode space over consuming base-ISA encodings.
  4. Prototype in software. Add it to an instruction-set simulator (Spike, QEMU) and the compiler or intrinsics, then rerun the workloads to measure instruction count.
  5. Model timing. Use a cycle-level simulator such as gem5 to see whether CPI holds up once caches and dependencies are included.
  6. Cost the hardware. Synthesize the RTL change for area, timing and power. A 1% cycle-time hit applies to every program.
  7. Count the long-term cost. Verification, compiler and OS support, documentation, and supporting the instruction for as long as the ISA exists.
Go further

Resources

Interactive tools and references

Peer-reviewed reading

  • Amdahl, G. M., Blaauw, G. A., & Brooks, F. P. (1964). Architecture of the IBM System/360. IBM Journal of Research and Development, 8(2), 87–101.Defines architecture as distinct from implementation; the origin of the ISA concept.doi.org/10.1147/rd.82.0087
  • Patterson, D. A., & Ditzel, D. R. (1980). The case for the reduced instruction set computer. ACM SIGARCH Computer Architecture News, 8(6), 25–33.The argument against ever-growing instruction sets.doi.org/10.1145/641914.641917
  • Radin, G. (1982). The 801 minicomputer. Proc. ASPLOS I, 39–47.IBM's early RISC design, built around what compilers actually needed.doi.org/10.1145/800050.801824
  • Patterson, D. A., & Séquin, C. H. (1982). A VLSI RISC. IEEE Computer, 15(9), 8–21.The Berkeley RISC I design and its register windows.doi.org/10.1109/MC.1982.1654133
  • Hennessy, J., et al. (1982). MIPS: A microprocessor architecture. Proc. MICRO-15, ACM SIGMICRO Newsletter, 13(4), 17–22.Stanford's ISA designed for pipelining, with software handling interlocks.doi.org/10.1145/1014194.800930
  • Fisher, J. A. (1983). Very long instruction word architectures and the ELI-512. Proc. ISCA, 140–150.The founding VLIW paper.doi.org/10.1145/800046.801649
  • Bhandarkar, D., & Clark, D. W. (1991). Performance from architecture: Comparing a RISC and a CISC with similar hardware organization. Proc. ASPLOS IV, 310–319.A controlled iron-law comparison of MIPS and VAX.doi.org/10.1145/106972.107003
  • Blem, E., Menon, J., & Sankaralingam, K. (2013). Power struggles: Revisiting the RISC vs. CISC debate on contemporary ARM and x86 architectures. Proc. IEEE HPCA, 1–12.Finds the ISA has little effect on modern performance and energy.doi.org/10.1109/HPCA.2013.6522302
  • Weaver, V. M., & McKee, S. A. (2009). Code density concerns for new architectures. Proc. IEEE ICCD, 459–464.Measures code size across dozens of ISAs.doi.org/10.1109/ICCD.2009.5413117
  • Peleg, A., & Weiser, U. (1996). MMX technology extension to the Intel architecture. IEEE Micro, 16(4), 42–50.How packed SIMD was retrofitted onto x86.doi.org/10.1109/40.526924
  • Stephens, N., et al. (2017). The ARM Scalable Vector Extension. IEEE Micro, 37(2), 26–39.Vector-length-agnostic design and why it matters.doi.org/10.1109/MM.2017.35
  • Codrescu, L., et al. (2014). Hexagon DSP: An architecture optimized for mobile multimedia and communications. IEEE Micro, 34(2), 34–43.A commercial VLIW DSP ISA shaped by its application.doi.org/10.1109/MM.2014.12
  • Gautschi, M., et al. (2017). Near-threshold RISC-V core with DSP extensions for scalable IoT endpoint devices. IEEE Transactions on VLSI Systems, 25(10), 2700–2713.The RI5CY extensions from the worked example, with measured gains.doi.org/10.1109/TVLSI.2017.2654506
  • Jouppi, N. P., et al. (2017). In-datacenter performance analysis of a tensor processing unit. Proc. ISCA, 1–12.A domain-specific accelerator with a small CISC-style instruction set.doi.org/10.1145/3079856.3080246
  • Gueron, S. (2009). Intel's new AES instructions for enhanced performance and security. Fast Software Encryption, LNCS 5665, 51–66.Application-specific instructions for speed and side-channel resistance.doi.org/10.1007/978-3-642-03317-9_4
  • Woodruff, J., et al. (2014). The CHERI capability model: Revisiting RISC in an age of risk. Proc. ISCA, 457–468.Adding memory safety at the ISA level.doi.org/10.1109/ISCA.2014.6853201
  • Sewell, P., et al. (2010). x86-TSO: A rigorous and usable programmer's model for x86 multiprocessors. Communications of the ACM, 53(7), 89–97.Formalizes the x86 memory model.doi.org/10.1145/1785414.1785443
  • Smith, J. E., & Nair, R. (2005). The architecture of virtual machines. IEEE Computer, 38(5), 32–38.ISA-level virtualization and binary translation.doi.org/10.1109/MC.2005.173
  • Haas, A., et al. (2017). Bringing the web up to speed with WebAssembly. Proc. ACM PLDI, 185–200.Design of a portable, verifiable virtual ISA.doi.org/10.1145/3062341.3062363
  • Hennessy, J. L., & Patterson, D. A. (2019). A new golden age for computer architecture. Communications of the ACM, 62(2), 48–60.Open ISAs and domain-specific architectures as the way forward.doi.org/10.1145/3282307