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 GPRwN= 32-bit GPR (low half of xN)qN= 128-bit FPR/vectordN= 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