NOTE: This document was largely AI-generated based on offlineasm/*.rb sources and offlineasm code in llint/*.asm files. Exercise healthy skepticism.
This document describes the correspondence between offlineasm logical registers, interpreter-specific aliases (LowLevelInterpreter and InPlaceInterpreter), and physical platform registers.
JavaScriptCore's offline assembler (offlineasm) uses portable logical register names that are mapped to platform-specific physical registers during code generation. The LowLevelInterpreter (LLInt) and InPlaceInterpreter (IPInt) define their own register aliases for clarity and portability.
| Offlineasm | LLInt Alias | IPInt Alias | ARM64/ARM64E | X86_64 | Purpose | 
|---|---|---|---|---|---|
| t0 | a0, wa0, r0 | wa0 | x0/w0 | rax | Argument 0 / Return value / Temp | 
| t1 | a1, wa1, r1 | wa1 | x1/w1 | rsi | Argument 1 / Temp | 
| t2 | a2, wa2 | wa2 | x2/w2 | rdx | Argument 2 / Temp | 
| t3 | a3, wa3 | wa3 | x3/w3 | rcx | Argument 3 / Temp | 
| t4 | a4, wa4 | wa4 | x4/w4 | r8 | Argument 4 / Temp | 
| t5 | a5, wa5 | wa5, PL (X86_64) | x5/w5 | r10 | Argument 5 / Temp / Pointer to Locals | 
| t6 | a6, wa6 | wa6, PL (ARM64) | x6/w6 | rdi | Argument 6 / Temp / Pointer to Locals | 
| t7 | a7, wa7 | wa7, PL (ARMv7) | x7/w7 | r9 | Argument 7 / Temp / Pointer to Locals | 
| t8 | - | - | x8/w8 | - | Temp | 
| t9 | ws0 | ws0, sc0 | x9/w9 | - | Wasm scratch 0 / Safe call 0 | 
| t10 | ws1 | ws1, sc1 | x10/w10 | - | Wasm scratch 1 / Safe call 1 | 
| t11 | ws2 | ws2 | x11/w11 | - | Wasm scratch 2 | 
| t12 | ws3 | ws3 | x12/w12 | - | Wasm scratch 3 | 
| Offlineasm | LLInt Alias | IPInt Alias | ARM64/ARM64E | X86_64 | Purpose | 
|---|---|---|---|---|---|
| cfr | - | - | x29 | rbp | Call Frame Register | 
| sp | - | - | sp | rsp | Stack Pointer | 
| lr | - | - | x30 (lr) | - | Link Register (ARM64 only) | 
| pc | - | - | - | - | Program Counter (logical) | 
| Offlineasm | LLInt Alias | IPInt Alias | ARM64/ARM64E | X86_64 | Purpose | 
|---|---|---|---|---|---|
| csr0 | - | WI (wasmInstance) | x19 | rbx | Callee-save / wasmInstance (IPInt) | 
| csr1 | - | MC (X86_64) | x20 | r12 | Callee-save / Metadata Counter (IPInt X86_64) | 
| csr2 | - | PC (X86_64) | x21 | r13 | Callee-save / Program Counter (IPInt X86_64) | 
| csr3 | - | MB (memoryBase) | x22 | r14 | Callee-save / Memory Base (IPInt) | 
| csr4 | - | BC (boundsCheckingSize) | x23 | r15 | Callee-save / Bounds Check (IPInt) | 
| csr5 | - | - | x24 | - | Callee-save (ARM64 only) | 
| csr6 | metadataTable | MC (ARM64) | x25 | - | Metadata Table (LLInt) / Metadata Counter (IPInt ARM64) | 
| csr7 | PB | PC (ARM64) | x26 | - | PB register (LLInt) / Program Counter (IPInt ARM64) | 
| csr8 | numberTag | - | x27 | - | Number tag (LLInt ARM64) | 
| csr9 | notCellMask | sc2 (RISCV64) | x28 | - | Not cell mask (LLInt ARM64) / Safe call 2 (IPInt RISCV64) | 
| csr10 | - | PL (RISCV64), sc3 (RISCV64) | - | - | Pointer to Locals / Safe call 3 (IPInt RISCV64) | 
| Offlineasm | LLInt Alias | IPInt Alias | ARM64/ARM64E | X86_64 | Purpose | 
|---|---|---|---|---|---|
| ft0 | fa0, wfa0, fr | - | q0/d0/s0 | xmm0 | FP argument 0 / return / temp | 
| ft1 | fa1, wfa1 | - | q1/d1/s1 | xmm1 | FP argument 1 / temp | 
| ft2 | fa2, wfa2 | - | q2/d2/s2 | xmm2 | FP argument 2 / temp | 
| ft3 | fa3, wfa3 | - | q3/d3/s3 | xmm3 | FP argument 3 / temp | 
| ft4 | wfa4 | - | q4/d4/s4 | xmm4 | Wasm FP temp | 
| ft5 | wfa5 | - | q5/d5/s5 | xmm5 | Wasm FP temp | 
| ft6 | wfa6 | - | q6/d6/s6 | xmm6 | Wasm FP temp | 
| ft7 | wfa7 | - | q7/d7/s7 | xmm7 | Wasm FP temp / scratch | 
| Offlineasm | LLInt Alias | IPInt Alias | ARM64/ARM64E | X86_64 | Purpose | 
|---|---|---|---|---|---|
| csfr0 | - | - | q8/d8 | - | Callee-save FP (ARM64 only) | 
| csfr1 | - | - | q9/d9 | - | Callee-save FP (ARM64 only) | 
| csfr2 | - | - | q10/d10 | - | Callee-save FP (ARM64 only) | 
| csfr3 | - | - | q11/d11 | - | Callee-save FP (ARM64 only) | 
| csfr4 | - | - | q12/d12 | - | Callee-save FP (ARM64 only) | 
| csfr5 | - | - | q13/d13 | - | Callee-save FP (ARM64 only) | 
| csfr6 | - | - | q14/d14 | - | Callee-save FP (ARM64 only) | 
| csfr7 | - | - | q15/d15 | - | Callee-save FP (ARM64 only) | 
| csfr8-11 | - | - | - | - | (Reserved) | 
| Offlineasm | LLInt Alias | IPInt Alias | ARM64/ARM64E | X86_64 | Purpose | 
|---|---|---|---|---|---|
| v0 | - | - | v16 (q16) | xmm0 | Vector register 0 | 
| v0_b | - | - | v16.b | xmm0 (byte) | Vector 0, byte elements | 
| v0_h | - | - | v16.h | xmm0 (half) | Vector 0, halfword elements | 
| v0_i | - | - | v16.s | xmm0 (int) | Vector 0, word elements | 
| v0_q | - | - | v16.d | xmm0 (quad) | Vector 0, doubleword elements | 
| v1 | - | - | v17 (q17) | xmm1 | Vector register 1 | 
| v1_b | - | - | v17.b | xmm1 (byte) | Vector 1, byte elements | 
| v1_h | - | - | v17.h | xmm1 (half) | Vector 1, halfword elements | 
| v1_i | - | - | v17.s | xmm1 (int) | Vector 1, word elements | 
| v1_q | - | - | v17.d | xmm1 (quad) | Vector 1, doubleword elements | 
| v2 | - | - | v18 (q18) | xmm2 | Vector register 2 | 
| v2_b | - | - | v18.b | xmm2 (byte) | Vector 2, byte elements | 
| v2_h | - | - | v18.h | xmm2 (half) | Vector 2, halfword elements | 
| v2_i | - | - | v18.s | xmm2 (int) | Vector 2, word elements | 
| v2_q | - | - | v18.d | xmm2 (quad) | Vector 2, doubleword elements | 
| v3 | - | - | v19 (q19) | xmm3 | Vector register 3 | 
| v3_b | - | - | v19.b | xmm3 (byte) | Vector 3, byte elements | 
| v3_h | - | - | v19.h | xmm3 (half) | Vector 3, halfword elements | 
| v3_i | - | - | v19.s | xmm3 (int) | Vector 3, word elements | 
| v3_q | - | - | v19.d | xmm3 (quad) | Vector 3, doubleword elements | 
| v4 | - | - | v20 (q20) | xmm4 | Vector register 4 | 
| v4_b | - | - | v20.b | xmm4 (byte) | Vector 4, byte elements | 
| v4_h | - | - | v20.h | xmm4 (half) | Vector 4, halfword elements | 
| v4_i | - | - | v20.s | xmm4 (int) | Vector 4, word elements | 
| v4_q | - | - | v20.d | xmm4 (quad) | Vector 4, doubleword elements | 
| v5 | - | - | v21 (q21) | xmm5 | Vector register 5 | 
| v5_b | - | - | v21.b | xmm5 (byte) | Vector 5, byte elements | 
| v5_h | - | - | v21.h | xmm5 (half) | Vector 5, halfword elements | 
| v5_i | - | - | v21.s | xmm5 (int) | Vector 5, word elements | 
| v5_q | - | - | v21.d | xmm5 (quad) | Vector 5, doubleword elements | 
| v6 | - | - | v22 (q22) | xmm6 | Vector register 6 | 
| v6_b | - | - | v22.b | xmm6 (byte) | Vector 6, byte elements | 
| v6_h | - | - | v22.h | xmm6 (half) | Vector 6, halfword elements | 
| v6_i | - | - | v22.s | xmm6 (int) | Vector 6, word elements | 
| v6_q | - | - | v22.d | xmm6 (quad) | Vector 6, doubleword elements | 
| v7 | - | - | v23 (q23) | xmm7 | Vector register 7 | 
| v7_b | - | - | v23.b | xmm7 (byte) | Vector 7, byte elements | 
| v7_h | - | - | v23.h | xmm7 (half) | Vector 7, halfword elements | 
| v7_i | - | - | v23.s | xmm7 (int) | Vector 7, word elements | 
| v7_q | - | - | v23.d | xmm7 (quad) | Vector 7, doubleword elements | 
- 
Register widths: - xN= 64-bit GPR
- wN= 32-bit GPR (low half of xN)
- qN= 128-bit FPR/vector
- dN= 64-bit FPR (double precision)
- sN= 32-bit FPR (single precision)
- vN= vector register with element type qualifier
 
- 
Scratch registers: x13, x16, x17 (not exposed in offlineasm) 
- 
FPR scratch: q31 
- 
Vector registers: Shared with FPRs (q0-q15 overlap with ft0-csfr7, q16-q23 used for v0-v7) 
- 
Register widths: - 64-bit: rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8-r15
- 32-bit: eax, ebx, ecx, edx, esi, edi, ebp, esp, r8d-r15d
- 16-bit: ax, bx, cx, dx, si, di, bp, sp, r8w-r15w
- 8-bit: al, bl, cl, dl, sil, dil, bpl, spl, r8b-r15b
 
- 
Scratch register: r11 (not exposed in offlineasm) 
- 
FPR scratch: xmm7 
- 
Limited callee-save: Only rbx, r12-r15 are callee-save 
| Purpose | Offlineasm | ARM64/ARM64E Physical | X86_64 Physical | Description | 
|---|---|---|---|---|
| PC (Program Counter) | csr7 | x26 | r13 | Bytecode program counter | 
| PB (Program Base) | csr7 | x26 | r13 | Same as PC in LLInt | 
| Metadata Table | csr6 | x25 | r12 | Metadata pointer | 
| Number Tag | csr8 | x27 | - | Number type tag (ARM64 only) | 
| Not Cell Mask | csr9 | x28 | - | Cell type mask (ARM64 only) | 
| Tag Type Number | csr3 | x22 | r14 | Type number for tagging | 
| Tag Mask | csr4 | x23 | r15 | Mask for type tags | 
| Wasm Instance | csr0 | x19 | rbx | WebAssembly instance pointer | 
| Arguments | t0-t7 | x0-x7 | rax,rsi,rdx,rcx,r8,r10,rdi,r9 | Function argument registers | 
| FP Arguments | ft0-ft3 | q0-q3 | xmm0-xmm3 | Floating-point arguments | 
| Wasm Scratch | t9-t12 (ws0-ws3) | x9-x12 | - | Wasm temporary registers | 
IPInt is the WebAssembly in-place interpreter with its own specialized register assignments:
| Purpose | Offlineasm | ARM64/ARM64E Physical | X86_64 Physical | ARMv7 Physical | RISCV64 Physical | Description | 
|---|---|---|---|---|---|---|
| PC (Program Counter) | csr7 | x26 | csr2 (r13) | csr1 | csr7 | IPInt bytecode position | 
| MC (Metadata Counter) | csr6 | x25 | csr1 (r12) | t6 | csr6 | Metadata pointer | 
| PL (Pointer to Locals) | t6 | x6 | t5 (r10) | t7 | csr10 | Address of local 0 | 
| WI (Wasm Instance) | csr0 | x19 | rbx | csr0 | csr0 | JSWebAssemblyInstance pointer | 
| MB (Memory Base) | csr3 | x22 | r14 | t2 (ARMv7) | csr3 | Wasm memory base address | 
| BC (Bounds Check) | csr4 | x23 | r15 | t3 (ARMv7) | csr4 | Wasm memory bounds size | 
| sc0 (safe for call) | ws0 (t9) | x9 | t9 | t4 | ws0 (t9) | Safe call register 0 | 
| sc1 (safe for call) | ws1 (t10) | x10 | t10 | t5 | ws1 (t10) | Safe call register 1 | 
| sc2 (safe for call) | ws2 (t11) | x11 | csr3 (r14) | csr0 | csr9 | Safe call register 2 | 
| sc3 (safe for call) | ws3 (t12) | x12 | csr4 (r15) | t7 | csr10 | Safe call register 3 | 
- PC (Program Counter): Records interpreter position in Wasm bytecode
- MC (Metadata Counter): Tracks corresponding position in generated metadata
- PL (Pointer to Locals): Fast access to local variables (points to local 0)
- WI (Wasm Instance): Current JSWebAssemblyInstance object (callee-save)
- MB (Memory Base): Current Wasm memory base address (callee-save)
- BC (Bounds Check): Size of Wasm memory region for bounds checking (callee-save)
- Safe call registers (sc0-sc3): Guaranteed not to overlap with argument registers, safe across calls
ARM64/ARM64E:
- Uses ldp/stp instructions for efficient register pair operations
- Memory registers (MB, BC) loaded via loadpairqfrom instance
X86_64:
- PC maps to csr2 instead of csr7 (different from LLInt)
- MC maps to csr1 instead of csr6 (different from LLInt)
- sc2 and sc3 reuse csr3/csr4 (MB/BC) as they're already in use
- Fewer argument registers (6 vs 8 on ARM64)
ARMv7:
- MB and BC use temporary registers (t2, t3) instead of callee-save
- More limited register set requires creative reuse
RISCV64:
- Similar to ARM64 in register allocation
- PL uses csr10 instead of t6
- Register definitions: Source/JavaScriptCore/offlineasm/registers.rb
- ARM64 mappings: Source/JavaScriptCore/offlineasm/arm64.rb
- X86_64 mappings: Source/JavaScriptCore/offlineasm/x86.rb
- LLInt code: Source/JavaScriptCore/llint/LowLevelInterpreter.asm
- IPInt code: Source/JavaScriptCore/llint/InPlaceInterpreter.asm