1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
# JavaScriptCore Offlineasm Register Reference
**NOTE: This document was largely AI-generated based on offlineasm/\*.rb sources and 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.
## Overview
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.
## General Purpose Registers (GPRs)
### Temporary Registers
| 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 |
### Special Purpose Registers
| 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) |
### Callee-Save Registers
| 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) |
## Floating Point Registers (FPRs)
### Temporary FP Registers
| 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 |
### Callee-Save FP Registers
| 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) |
## Vector Registers
### SIMD/Vector Registers
| 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 |
## Platform-Specific Notes
### ARM64/ARM64E
- **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)
### X86_64
- **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
## Register Conventions Summary
### LowLevelInterpreter (LLInt) Conventions
| 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 |
### InPlaceInterpreter (IPInt) Conventions
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 |
#### IPInt Special Notes
- **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
#### Platform-Specific IPInt Notes
**ARM64/ARM64E:**
- Uses ldp/stp instructions for efficient register pair operations
- Memory registers (MB, BC) loaded via `loadpairq` from 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
## Source Files
- **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`
|