This appendix collects side-by-side comparison tables for the three reference ISAs of the book: x86-64, AArch64 (ARMv8-A 64-bit), and RISC-V (RV64GC). It serves as a quick lookup for the differences and similarities. Each ISA is covered in depth in its own Part of the book (Parts VII, VIII, IX); here we focus on direct comparison.
| Aspect | x86-64 | AArch64 | RISC-V |
|---|
| Style | CISC (with µops) | RISC | RISC |
| Year introduced | 2003 (AMD64) | 2011 | 2011 (ratified later) |
| Encoding | Variable (1-15 bytes) | Fixed 32-bit | 16-bit (C ext.) or 32-bit |
| License | Proprietary (Intel, AMD, VIA) | Proprietary (ARM Holdings) | Open / royalty-free |
| Typical implementation | Decode → µops → OoO | Direct decode (some µop fusion) | Direct decode |
| Address size | 48-bit virtual, 52-bit physical | 48-bit (extensible to 52, 56) | 39/48/57-bit |
| Endianness | Little | Bi (typically little) | Bi (typically little) |
| Memory model | TSO (mostly) | Weak (release/acquire) | Weak (RVWMO) |
| Pages typical | 4 KiB, 2 MiB, 1 GiB | 4/16/64 KiB, 2 MiB, 1 GiB, 512 GiB | 4 KiB, 2 MiB, 1 GiB, 512 GiB |
| Vendors | Intel, AMD | Apple, Qualcomm, ARM, Ampere, AWS, Samsung, MediaTek, NVIDIA | SiFive, Western Digital, Alibaba (T-Head), Tenstorrent, Andes, ESP32-C, GD32V, many |
| x86-64 | AArch64 | RISC-V |
|---|
| Count (general purpose) | 16 | 31 (+ ZR) | 31 (+ x0=zero) |
| Width | 64-bit | 64-bit | 64-bit (or 32 for RV32) |
| Hardwired zero | (none) | xzr/wzr | x0 |
| Stack pointer | rsp | sp | x2 (sp) |
| Frame pointer | rbp (optional) | x29 (FP) | x8 (s0/fp) |
| Link/return | (on stack) | x30 (LR) | x1 (ra) |
rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8-r15. Each has 32-bit (eax...), 16-bit (ax...), and 8-bit (al, ah...) sub-views; writing the 32-bit half zero-extends to 64-bit.
x0-x30 (64-bit views), w0-w30 (32-bit views, zero-extended on write). Plus xzr/wzr (zero) and sp (stack pointer, used in some addressing modes).
x0-x31. ABI names: zero, ra, sp, gp, tp, t0-t6, s0-s11, a0-a7. x0 is hardwired zero.
| x86-64 | AArch64 | RISC-V |
|---|
| FP/SIMD register count | 16 (xmm0-xmm15) extended to 32 (zmm0-zmm31) with AVX-512 | 32 (v0-v31) | 32 (f0-f31) for F/D ext.; 32 vector regs for V ext. |
| Scalar FP width | 64 (in SSE/AVX), 80 (legacy x87) | 32 / 64 | 32 (F), 64 (D), 128 (Q) |
| SIMD width | 128 (SSE), 256 (AVX), 512 (AVX-512) | 128 (NEON), 128/256/.../2048 (SVE/SVE2) | Vector length is implementation-defined (vlen) |
| FMA | yes (FMA3) | yes (FMA from start) | yes (F/D include FMADD) |
| Vector model | Fixed-width SIMD | Fixed (NEON) + variable (SVE) | Variable (V extension, "vector-length agnostic") |
| x86-64 (System V) | x86-64 (Microsoft) | AArch64 | RISC-V |
|---|
| Arg 1 | rdi | rcx | x0 | a0 |
| Arg 2 | rsi | rdx | x1 | a1 |
| Arg 3 | rdx | r8 | x2 | a2 |
| Arg 4 | rcx | r9 | x3 | a3 |
| Arg 5 | r8 | (stack) | x4 | a4 |
| Arg 6 | r9 | (stack) | x5 | a5 |
| Arg 7 | (stack) | (stack) | x6 | a6 |
| Arg 8 | (stack) | (stack) | x7 | a7 |
| Return | rax | rax | x0 | a0 |
| x86-64 SysV | AArch64 | RISC-V |
|---|
| First N float args | xmm0-xmm7 | v0-v7 | fa0-fa7 |
| ISA | Callee-saved integer | Callee-saved float |
|---|
| x86-64 SysV | rbx, rbp, r12-r15 | (all xmm caller-saved) |
| x86-64 Win | rbx, rbp, rdi, rsi, r12-r15 | xmm6-xmm15 |
| AArch64 | x19-x29 | v8-v15 (low 64 bits only) |
| RISC-V | s0-s11 (x8-x9, x18-x27) | fs0-fs11 |
| ISA | Alignment at call | Direction |
|---|
| x86-64 | 16 bytes | Grows down |
| AArch64 | 16 bytes | Grows down |
| RISC-V | 16 bytes | Grows down |
The most flexible: [base + index*scale + displacement] with scale ∈ , plus PC-relative [rip + disp].
Examples:
mov rax, [rbx]
mov rax, [rbx + 8]
mov rax, [rbx + rcx]
mov rax, [rbx + rcx*4 + 16]
mov rax, [rip + symbol] (PC-relative)
Several modes; richer than RISC-V but more uniform than x86-64:
- Immediate:
[xn, #imm]
- Register:
[xn, xm], optionally with shift/extend ([xn, wm, sxtw #2])
- Pre-indexed:
[xn, #imm]! (writeback of new address into xn)
- Post-indexed:
[xn], #imm (use xn, then xn += imm)
- PC-relative:
[label] or adrp + add for symbols
Only [base + 12-bit signed offset] for loads/stores. Larger offsets and indexing must be computed explicitly with arithmetic instructions.
For PC-relative: auipc + addi (or other) builds an address; pseudo-instructions like la rd, symbol expand to this.
| x86-64 Linux | AArch64 Linux | RISC-V Linux |
|---|
| Instruction | syscall | svc #0 | ecall |
| Syscall number | rax | x8 | a7 |
| Args | rdi, rsi, rdx, r10, r8, r9 | x0-x5 | a0-a5 |
| Return | rax | x0 | a0 |
| Errno style | negative rax | negative x0 | negative a0 |
(Note: Linux on x86-64 uses r10 for arg 4, not rcx, because syscall clobbers rcx.)
| x86-64 | AArch64 | RISC-V |
|---|
| User | Ring 3 | EL0 | U-mode |
| Kernel | Ring 0 | EL1 | S-mode |
| Hypervisor | VMX root / SVM | EL2 | HS-mode (H ext.) |
| Firmware/Secure | SMM | EL3 (TrustZone) | M-mode |
| Levels | 4 + SMM + VMX | 4 (EL0-EL3) | 3 (M, S, U) + virtualized variants |
| x86-64 | AArch64 | RISC-V |
|---|
| Levels (4 KiB pages) | 4 (PML4) or 5 (LA57) | 4 | Sv39 (3), Sv48 (4), Sv57 (5) |
| Page sizes | 4K, 2M, 1G | 4K, 16K, 64K (granule); plus block sizes | 4K, 2M, 1G, ... |
| TLB invalidate | INVLPG, INVPCID | TLBI | SFENCE.VMA |
| Process tag | PCID | ASID | ASID |
| x86-64 | AArch64 | RISC-V |
|---|
| Controller | LAPIC, IO-APIC, MSI/MSI-X | GIC (v3, v4) | PLIC, CLINT, AIA (newer) |
| IRQ entry | IDT (256 vectors) | Vector base reg (VBAR) | mtvec/stvec |
| Disable IRQ | cli, sti | msr daifset/daifclr | csrrw mstatus.MIE |
x86-64: 256 vectors at offsets in IDT.
AArch64: 16-entry table at VBAR; 4 categories × 4 sources.
RISC-V: 1 base + 4 cause categories (or vectored mode with 1 entry per cause).
| x86-64 | AArch64 | RISC-V |
|---|
| Default model | TSO | RCsc / RCpc (release-consistency) | RVWMO (weak) |
| Atomic load-store | mov (aligned ≤ 64 bits is atomic) | ldr/str (with proper alignment) | lw/sw (aligned) |
| Acquire load | mov (TSO) | ldar | lr / ld + fence rw,rw or load + fence r,rw |
| Release store | mov (TSO) | stlr | sd + fence rw,w |
| RMW atomic | lock-prefixed (lock add, lock cmpxchg, xadd) | LL/SC (ldxr/stxr) or LSE (ldadd, etc.) | LR/SC (lr.w/sc.w) or AMO (amoadd.w, etc.) |
| Full barrier | mfence | dmb sy | fence rw,rw |
| Compiler barrier | (asm volatile) | (asm volatile) | (asm volatile) |
| lock cmpxchg [mem], reg ; CAS |
| lock xadd [mem], reg ; fetch-and-add |
| lock or/and/xor [mem], reg ; atomic Boolean |
| xchg [mem], reg ; (always atomic, no lock prefix needed) |
| ldxr / stxr ; load-exclusive / store-exclusive (LL/SC) |
| ldaxr / stlxr ; with acquire/release ordering |
| ldadd / ldset / ldclr / ldeor / swp / cas (LSE extension; v8.1+) |
| lr.w / sc.w ; load-reserved / store-conditional |
| amoadd.w/d, amoswap.w/d, amoand.w/d, amoor.w/d, amoxor.w/d, amomax.w/d, amomin.w/d (with .aq/.rl variants) |
| Operation | x86-64 | AArch64 | RISC-V |
|---|
| Compare and branch | cmp + jcc | cmp + b.cc, or cbz/cbnz, or tbz/tbnz | beq/bne/blt/bge/bltu/bgeu |
| Conditional move | cmov | csel, cset | (with Zicond ext.) |
| Function call | call | bl | jal / call (pseudo) |
| Return | ret | ret (= br x30) | jr ra (= ret pseudo) |
x86-64 has flag-based branching: arithmetic instructions set flags; branches read flags. AArch64 also has flags (NZCV) but adds compare-and-branch (cbz/cbnz) and test-and-branch (tbz/tbnz) that don't depend on flags. RISC-V has no flags; branches compare two registers directly.
| Operation | x86-64 | AArch64 | RISC-V |
|---|
| Population count | popcnt (SSE4.2) | cnt (NEON), cnt (Armv9) | cpop (Zbb) |
| Leading zero count | lzcnt (BMI1, AMD ABM) | clz | clz (Zbb) |
| Trailing zero count | tzcnt (BMI1) | (rbit + clz) | ctz (Zbb) |
| Bit reverse | (no native; movbe is byte) | rbit | (Zbkb) |
| Byte swap | bswap | rev | rev8 (Zbb) |
| Bit field extract | bextr (BMI2) | ubfx, sbfx | (Zbb varies) |
| Bit field insert | (no direct) | bfi | (varies) |
| ISA | Vector instruction set | Width | Predication |
|---|
| x86-64 | SSE/SSE2/SSE3/SSSE3/SSE4 → AVX/AVX2 → AVX-512 → AVX-10 | 128 / 256 / 512 | Mask registers (k0-k7) on AVX-512 |
| AArch64 | NEON (advanced SIMD) | 128 | Lane operations |
| AArch64 | SVE / SVE2 | 128 to 2048 | Predicate registers (p0-p15) |
| RISC-V | Vector ext. (V) | implementation-defined (vlen) | mask register (v0) |
| x86-64 | AArch64 | RISC-V |
|---|
| Min instr length | 1 byte | 4 bytes | 2 bytes (C ext.) |
| Max instr length | 15 bytes | 4 bytes | 4 bytes |
| Decode complexity | High | Moderate | Low |
| Average code density | Highest | Lower than x86 | Highest with C ext. |
| Code-section size | Smallest | ~10-20% larger | Comparable to x86 with C |
All three ISAs have AES, SHA, and CRC instructions:
| x86-64 | AArch64 | RISC-V |
|---|
| AES | AES-NI | Crypto ext. | Zk* extensions |
| SHA | SHA-NI | Crypto ext. | Zk* extensions |
| CRC | crc32 (SSE4.2) | crc32 | (Zbc) |
| x86-64 | AArch64 | RISC-V |
|---|
| Hardware-assisted | Intel VT-x, AMD-V | EL2 (host hypervisor mode) | H extension (HS-mode) |
| Nested page tables | EPT (Intel), NPT (AMD) | Stage-2 translation | Two-stage translation |
| Interrupt virt. | APICv (Intel), AVIC (AMD) | GIC virtualization | AIA virtualization |
| IOMMU | VT-d (Intel), AMD-Vi | SMMU (v2, v3) | IOMMU spec (newer) |
| x86-64 | AArch64 | RISC-V |
|---|
| W^X (NX bit) | yes | yes | yes |
| ASLR | yes | yes | yes |
| Stack canaries | yes (compiler) | yes (compiler) | yes (compiler) |
| Pointer authentication | (no native) | PAC (Armv8.3+) | (under proposal: Zicfilp + others) |
| Branch target identification | CET (IBT) | BTI (Armv8.5+) | Zicfilp (CFI) |
| Shadow stack | CET (Shadow Stack) | (under specification) | Zicfiss |
| Memory tagging | (no native) | MTE (Armv8.5+) | (under proposal) |
| Trusted execution | SGX (deprecated), TDX | TrustZone, CCA (Realm Management) | (vendor-specific) |
| Encrypted memory | SME, SEV | (vendor) | (vendor) |
| x86-64 | AArch64 | RISC-V |
|---|
| Counter access | RDPMC (priv-controlled) | mrs from PMU registers | hpmcounter CSRs |
| Sampling | PEBS (Intel), IBS (AMD) | SPE (Statistical Profiling Extension) | (under proposal) |
| Event count | hundreds of events | dozens to hundreds (impl-specific) | hundreds (impl-specific) |
| Top-down counters | yes (Intel TMA) | yes (Topdown methodology, recent) | (under development) |
| x86-64 | AArch64 | RISC-V |
|---|
| GCC | mature (since 2003) | mature (since v4.8) | mature (RV64GC since v8) |
| LLVM | mature | mature | mature |
| Linux | first-class | first-class | first-class |
| Windows | first-class | first-class (since 2017) | (Windows on RISC-V experimental) |
| macOS | (legacy; Intel Macs) | first-class (Apple Silicon) | (no) |
| Android | yes | first-class | experimental |
| Embedded | (rare in MCUs) | (Cortex-M is not AArch64) | extensive (ESP32-C, GD32V, etc.) |
x86-64: When you need to run existing Windows / Linux / macOS-Intel software unchanged; for PC-class workloads with the broadest software ecosystem; for high-end servers.
AArch64: When you want power efficiency at smartphone or laptop scale (Apple Silicon, Snapdragon, MediaTek); for cloud servers (Graviton, Ampere); for embedded systems requiring more compute than Cortex-M offers; for Apple, Android, and increasingly Windows ARM.
RISC-V: When you want freedom from licensing fees and proprietary control; when you want to customize the ISA (add domain-specific extensions); for academic and research work; for emerging applications where the cost / openness matters more than ecosystem maturity (small embedded systems, AI accelerators with embedded RISC-V management cores).
The boundaries blur. AArch64 dominates mobile, has a strong server presence, and is gaining laptop share. x86-64 dominates desktop, owns most laptops, and remains entrenched in the server market. RISC-V leads in embedded AI/microcontroller spaces and is rapidly growing into adjacent territory.
This appendix has provided side-by-side comparisons across registers, calling conventions, addressing modes, system architecture, memory models, atomics, vector extensions, code density, security features, and ecosystem maturity. Each ISA has a coherent design philosophy:
- x86-64: backward compatibility, code density, rich addressing, TSO simplicity, with the cost of complex decoders.
- AArch64: a clean RISC redesign with strong vector and security extensions, a balance of code density and decode simplicity.
- RISC-V: minimal base + composable extensions, openness, and the ability to customize.
Choose by the constraints of your workload, ecosystem, and customization needs.