-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
463 lines (443 loc) · 29.7 KB
/
Copy pathindex.html
File metadata and controls
463 lines (443 loc) · 29.7 KB
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
---
# Front matter so Jekyll renders the latest-post highlight below the hero.
# The rest of this page is plain HTML and is passed through unchanged.
layout: null
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Digitalis — ARM64-to-x86_64 Binary Translation</title>
<meta name="description" content="Run ARM64 Android apps on x86_64 emulators. Digitalis translates ARM64 instructions to native x86_64 machine code at runtime using JIT compilation, built on AOSP 16.">
<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32.png">
<link rel="apple-touch-icon" href="assets/favicon-180.png">
<link rel="stylesheet" href="/assets/theme.css">
<link rel="stylesheet" href="style.css">
{%- include theme-head.html %}
<!-- Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LCH8R0W6KL"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-LCH8R0W6KL');
</script>
</head>
<body>
{% include nav.html %}
<!-- Hero -->
<header class="hero">
<div class="container">
<img class="hero-logo" src="assets/digitalis-icon.png" alt="" width="88" height="88">
<h1 class="hero-title">DIGITALIS</h1>
<p class="hero-tagline">ARM64-to-x86_64 binary translation for Android · built on AOSP 16</p>
<!-- Only the call to action lives here now; Verified Apps, Docs, Blog and
GitHub are all one click away in the nav above, and repeating them
made the hero a second copy of it. -->
<div class="hero-buttons">
<a href="#getting-started" class="btn btn-primary">Get Started</a>
</div>
</div>
</header>
<!-- Latest post -->
{% assign latest = site.posts.first %}{% if latest %}
<section class="latest-post-section">
<div class="container">
<a class="latest-post" href="{{ latest.url | relative_url }}">
<span class="latest-post-flag">Latest post</span>
<span class="latest-post-body">
<span class="latest-post-title">{{ latest.title }}</span>
<span class="latest-post-meta"><time datetime="{{ latest.date | date_to_xmlschema }}">{{ latest.date | date: "%B %-d, %Y" }}</time>{% if latest.summary %} · {{ latest.summary }}{% endif %}</span>
</span>
<span class="latest-post-arrow" aria-hidden="true">→</span>
</a>
</div>
</section>
{% endif %}
<!-- Architecture -->
<section id="architecture">
<div class="container">
<h2 class="section-title">Architecture</h2>
<p class="section-desc"><a href="https://cs.android.com/android/platform/superproject/main/+/main:frameworks/libs/binary_translation/" target="_blank" rel="noopener">Berberis</a> is AOSP's binary translation framework, part of Android's NativeBridge system. It provides the core infrastructure for translating guest architecture instructions to host machine code at runtime — including a JIT compiler, an interpreter, an instruction decoder, syscall emulation, and proxy libraries. Berberis currently supports RISC-V-to-x86_64 translation in upstream AOSP.</p>
<p class="section-desc">Google's own emulator images go further than the published source. The <strong>Google APIs</strong> x86_64 system images register <code>ro.dalvik.vm.native.bridge=libndk_translation.so</code> — from Android 14 through <strong>Android 17</strong> (API 37) in the images we checked — and that binary is Berberis with an <strong>ARM64</strong> backend: its symbol table carries <code>berberis::intrinsics::Arm64ReadFpcr</code> and <code>Arm64ReadFpsr</code>, and the images ship <code>/system/etc/berberis/cpuinfo.arm64.txt</code>, <code>/system/etc/init/berberis_arm_or_arm64.rc</code> and <code>arm64_dyn</code>/<code>arm64_exe</code> binfmt_misc handlers. That ARM64 implementation is <strong>not published</strong> — upstream AOSP Berberis carries only the RISC-V backend, and the plain AOSP images ship no native bridge at all. Digitalis is an open ARM64 backend built on the public framework.</p>
<div class="pipeline-label">Berberis (upstream AOSP)</div>
<div class="pipeline">
<div class="pipeline-step">RISC-V APK</div>
<span class="pipeline-arrow">→</span>
<div class="pipeline-step">NativeBridge</div>
<span class="pipeline-arrow">→</span>
<div class="pipeline-step">JIT / Interpreter</div>
<span class="pipeline-arrow">→</span>
<div class="pipeline-step">x86_64 Host</div>
</div>
<p class="section-desc">Digitalis extends Berberis with an ARM64 backend, enabling ARM64-only Android apps to run on x86_64 emulators. It reuses Berberis's translation infrastructure while adding ARM64 instruction decoding, JIT code generation, and interpreter support. Guest code runs through three tiers: an interpreter, a single-pass lite translator (first gear) for cold regions, and an optimizing heavy translator (second gear) that engages on hot regions. The tree is an <strong>AOSP 16</strong> (API 36) checkout, and the emulator image everything here is measured on is built from it.</p>
<div class="pipeline-label">Digitalis (this project)</div>
<div class="pipeline">
<div class="pipeline-step">ARM64 APK</div>
<span class="pipeline-arrow">→</span>
<div class="pipeline-step">NativeBridge</div>
<span class="pipeline-arrow">→</span>
<div class="pipeline-step">Interpreter / Lite / Heavy JIT</div>
<span class="pipeline-arrow">→</span>
<div class="pipeline-step">x86_64 Host</div>
</div>
<div class="arch-details">
<div class="arch-detail">
<h3>Interpreter</h3>
<p>Per-instruction fallback for syscalls, complex SIMD operations, and edge cases the JIT can't handle.</p>
<span class="tag">fallback path</span>
</div>
<div class="arch-detail">
<h3>Lite Translator (first gear)</h3>
<p>Single-pass JIT that translates cold ARM64 regions to native x86_64 machine code. Handles ~98% of instructions. Translated regions are cached for reuse.</p>
<span class="tag">~98% coverage</span>
</div>
<div class="arch-detail">
<h3>Heavy Optimizer (second gear)</h3>
<p>An optimizing JIT that re-compiles a region once a hotness counter says it has earned it, doing global register allocation and loop optimization across the whole region. It covers essentially the same instruction surface as the lite tier, so real-app hot loops gear up instead of settling at first-gear speed.</p>
<span class="tag">hot-region tier</span>
</div>
</div>
<p class="section-desc" style="margin-top:32px">Two ways to go deeper, same system: take the <a href="docs.html">guided tour</a> — 102 slides, in order, assuming no background — or search the full <a href="https://github.com/DigitalisX64/digitalis/blob/android-latest-release/docs/how-it-works.md" target="_blank" rel="noopener"><code>how-it-works.md</code></a>, the complete walkthrough covering register mapping, translation lifecycle, NZCV flag emulation, the syscall path, proxy library forwarding, and the ARM64 → x86_64 instruction-mapping reference. Both, plus the benchmark and coverage tables, are listed under <a href="docs.html">Docs</a>.</p>
</div>
</section>
<!-- Features -->
<section id="features">
<div class="container">
<h2 class="section-title">Features</h2>
<div class="features-grid">
<div class="feature-card">
<h3>Two-Gear JIT Compiler</h3>
<p>Translation happens in two gears. Both emit native x86_64 machine code, and both cache what they produce, so a region is translated once and then simply run.</p>
<ul class="feature-list">
<li><strong>First gear — the Lite Translator.</strong> A single pass over a cold region, covering ~98% of the instruction set with no optimisation. Its job is to get working native code as quickly as possible — and to keep regions whole: the register allocator holds a fixed six-register scratch reserve so that running out of registers spills through memory instead of splitting the region, an invariant that eliminated 70,000+ measured region splits at function prologues across a 14-app sweep.</li>
<li><strong>Second gear — the Heavy Optimizer.</strong> Re-compiles a region once it has proved hot, with global register allocation and loop optimisation across the whole region. Neutral-or-faster than first gear in general, up to ~2x on register-pressure-heavy loops.</li>
<li><strong>Checked against itself.</strong> 3,600+ host translation tests, plus differential fuzzers that run the same code through the JIT and the interpreter and compare the entire CPU state afterwards.</li>
</ul>
</div>
<div class="feature-card">
<h3>Interpreter Fallback</h3>
<p>Per-instruction execution for syscalls, complex SIMD, and anything the JIT can't handle. Ensures complete ARM64 coverage.</p>
</div>
<div class="feature-card">
<h3>Proxy Libraries</h3>
<p>A guest ARM64 library cannot call the host's x86_64 one directly. <strong>21 proxy libraries</strong> stand on that boundary — Vulkan, libc/libm, EGL/GLES, AAudio, camera, NDK binder, NNAPI, JNI helpers — translating each call and forwarding it to the native implementation.</p>
<ul class="feature-list">
<li><strong>Graphics reach the real GPU.</strong> Vulkan goes through GFXStream's VkDecoder; OpenGL ES is driven by ANGLE, which implements it on top of Vulkan in-guest — giving full OpenGL ES 3.2 and hardware MSAA on the host GPU.</li>
<li><strong>Awkward symbols are covered by hand.</strong> Anything the auto-generated marshallers can't handle gets a custom trampoline written in-surface — <code>JNIEnv</code> translation, host→guest callbacks, and the ~80 ANGLE extension procs a browser engine gates on but <code>eglGetProcAddress</code> would otherwise return NULL for.</li>
<li><strong>The boundary is where the subtle bugs live.</strong> A zero stride from <code>ANativeWindow_lock</code> made a video app render solid green; a guard-page read inside the allocator wrappers looked for weeks like host memory exhaustion. Both fixed here — and the stride now comes from <em>asking the host allocator</em> rather than assuming the format's rule, because row padding is gralloc's choice, not the pixel format's.</li>
<li><strong>Probed systematically, not just when apps break.</strong> Eight dedicated samples now stress the riskiest marshalling paths — host-invoked guest callbacks, buffer handles crossing unix sockets, fd passing, <code>JNIEnv</code> round-trips — and all of them pass; the only failures they ever found reproduced identically on native x86_64 builds, i.e. they were Android platform behaviour, not translation.</li>
<li><strong>No reachable call aborts, audio included.</strong> The OpenSL ES and OpenMAX AL proxies wrap host interface vtables method by method, and the methods upstream could not marshal used to kill the process on first call. A named-override seam now supplies working marshalling for every one an app can reach — the streaming-decode buffer-queue callback fires from host code back into translated guest code — closing the last known app-reachable aborts across all 21 proxies.</li>
</ul>
</div>
<div class="feature-card">
<h3>150 Sample Apps</h3>
<p>Every sample is an <strong>ARM64-only</strong> APK that runs end to end on the x86_64 emulator: ported NDK samples, third-party native libraries, whole UI engines, and one probe per ARM64 instruction extension.</p>
<ul class="feature-list">
<li><strong>Real libraries, linked the way an app links them.</strong> OpenCV, TensorFlow Lite, PyTorch, ONNX Runtime, FFmpeg, WebRTC, Qt 6, React Native, Realm, SQLCipher and dozens more — not reimplementations written to be easy to translate.</li>
<li><strong>A wrong answer fails, loudly.</strong> The ML, audio, crypto and binder samples check their output <em>bit-exact</em> against a hardcoded golden, so a miscompiled NEON kernel aborts instead of quietly rendering something slightly wrong.</li>
<li><strong>One sample per extension.</strong> NEON, FP16, BF16, dot-product, I8MM, complex arithmetic, JSCVT, PAC, BTI, the LSE and LRCPC atomics, CRC32 and the crypto instructions each get a probe that runs hot enough to reach the optimising JIT tier.</li>
<li><strong>One probe per proxied NDK surface.</strong> Eight samples exercise the full public API of a proxy library each — AHardwareBuffer, AImageDecoder, the media data-source/muxer pair, the ADPF hint/thermal/choreographer trio, ASharedMemory, system fonts, OpenMAX AL, OpenSL ES — with golden self-checks on every call, so a marshalling bug fails a specific assertion instead of corrupting an app somewhere downstream.</li>
</ul>
<p style="margin-top:14px">The full catalogue is grouped by subsystem <a href="#samples">further down the page</a>.</p>
</div>
</div>
</div>
</section>
<!-- Getting Started -->
<section id="getting-started">
<div class="container">
<h2 class="section-title">Getting Started</h2>
<div class="terminal">
<div><span class="comment"># Clone</span></div>
<div><span class="prompt">$ </span><span class="command">mkdir digitalis && cd digitalis</span></div>
<div><span class="prompt">$ </span><span class="command">repo init -b android-latest-release -u git@github.com:DigitalisX64/manifest.git</span></div>
<div><span class="prompt">$ </span><span class="command">repo sync -c -d --no-tags --force-sync</span></div>
<div> </div>
<div><span class="comment"># Build</span></div>
<div><span class="prompt">$ </span><span class="command">source build/envsetup.sh</span></div>
<div><span class="prompt">$ </span><span class="command">lunch sdk_phone64_x86_64_digitalis-trunk_staging-userdebug</span></div>
<div><span class="prompt">$ </span><span class="command">m</span></div>
<div> </div>
<div><span class="comment"># Run emulator</span></div>
<div><span class="prompt">$ </span><span class="command">emulator -memory 4096 -writable-system -qemu -cpu host &</span></div>
<div> </div>
<div><span class="comment"># Install and test</span></div>
<div><span class="prompt">$ </span><span class="command">cd sample/hellodigitalis && ./gradlew assembleDebug</span></div>
<div><span class="prompt">$ </span><span class="command">adb install hello-vulkan/build/outputs/apk/debug/hello-vulkan-debug.apk</span></div>
<div><span class="prompt">$ </span><span class="command">adb shell am start -n com.example.hellodigitalis/android.app.NativeActivity</span></div>
</div>
</div>
</section>
<!-- Sample Apps -->
<section id="samples">
<div class="container">
<h2 class="section-title">Sample Apps</h2>
<p class="section-desc">ARM64-only APKs running on an x86_64 emulator via NativeBridge translation.</p>
<div class="terminal">
<div><span class="comment"># Build all sample modules (ARM64-only APKs)</span></div>
<div><span class="prompt">$ </span><span class="command">cd sample/hellodigitalis && ./gradlew assembleDebug</span></div>
<div> </div>
<div><span class="comment"># Install and run</span></div>
<div><span class="prompt">$ </span><span class="command">adb install hello-vulkan/build/outputs/apk/debug/hello-vulkan-debug.apk</span></div>
<div><span class="prompt">$ </span><span class="command">adb shell am start -n com.example.hellodigitalis/android.app.NativeActivity</span></div>
<div><span class="success">✓ Vulkan triangle rendered via NativeBridge translation</span></div>
</div>
<div class="sample-groups">
<div class="sample-group">
<h3 class="sample-group-title">Graphics & GPU <span class="sample-group-count">20</span></h3>
<p class="sample-group-desc">Vulkan, OpenGL ES 1.x/2/3, EGL, and renderers</p>
<div class="samples-grid">
<div class="sample-item">hello-vulkan</div>
<div class="sample-item">hello-gl2</div>
<div class="sample-item">gles3jni</div>
<div class="sample-item">hello-gles1</div>
<div class="sample-item">hello-gles3</div>
<div class="sample-item">hello-msaa</div>
<div class="sample-item">hello-eglext</div>
<div class="sample-item">teapots-classic</div>
<div class="sample-item">teapots-more</div>
<div class="sample-item">teapots-textured</div>
<div class="sample-item">bitmap-plasma</div>
<div class="sample-item">endless-tunnel</div>
<div class="sample-item">hello-filament</div>
<div class="sample-item">hello-gltfio</div>
<div class="sample-item">hello-filament-render</div>
<div class="sample-item">hello-rive</div>
<div class="sample-item">hello-libpag</div>
<div class="sample-item">hello-graphics-path</div>
<div class="sample-item">hello-ink</div>
<div class="sample-item">hello-webview-functor</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">NDK platform surface <span class="sample-group-count">24</span></h3>
<p class="sample-group-desc">The Android APIs a native app actually calls</p>
<div class="samples-grid">
<div class="sample-item">native-activity</div>
<div class="sample-item">hello-hardwarebuffer</div>
<div class="sample-item">hello-imagedecoder</div>
<div class="sample-item">hello-adpf</div>
<div class="sample-item">hello-sharedmem</div>
<div class="sample-item">hello-fonts</div>
<div class="sample-item">hello-jni</div>
<div class="sample-item">hello-jniCallback</div>
<div class="sample-item">native-midi</div>
<div class="sample-item">sensor-graph</div>
<div class="sample-item">camera-basic</div>
<div class="sample-item">camera-texture-view</div>
<div class="sample-item">hello-camera-core</div>
<div class="sample-item">hello-binder-ndk</div>
<div class="sample-item">hello-nnapi</div>
<div class="sample-item">hello-libc-libm</div>
<div class="sample-item">hello-tracing-perfetto</div>
<div class="sample-item">hello-sigaction</div>
<div class="sample-item">hello-superpack-regress</div>
<div class="sample-item">sanitizers</div>
<div class="sample-item">vectorization</div>
<div class="sample-item">orderfile</div>
<div class="sample-item">exceptions</div>
<div class="sample-item">unit-test</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Audio <span class="sample-group-count">6</span></h3>
<p class="sample-group-desc">Playback, capture, and the low-latency paths</p>
<div class="samples-grid">
<div class="sample-item">native-audio</div>
<div class="sample-item">hello-aaudio</div>
<div class="sample-item">hello-oboe</div>
<div class="sample-item">hello-opus</div>
<div class="sample-item">hello-openmaxal</div>
<div class="sample-item">hello-opensles</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Media & codecs <span class="sample-group-count">9</span></h3>
<p class="sample-group-desc">Players, transcoding, and real-time streams</p>
<div class="samples-grid">
<div class="sample-item">native-codec</div>
<div class="sample-item">hello-mediandk-source</div>
<div class="sample-item">hello-ijkplayer</div>
<div class="sample-item">hello-libvlc</div>
<div class="sample-item">hello-ffmpeg-kit</div>
<div class="sample-item">hello-webrtc</div>
<div class="sample-item">hello-libwebp</div>
<div class="sample-item">hello-avif</div>
<div class="sample-item">hello-gif</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Imaging, PDF & maps <span class="sample-group-count">9</span></h3>
<p class="sample-group-desc">Pixel pipelines and vector rendering</p>
<div class="samples-grid">
<div class="sample-item">hello-fresco</div>
<div class="sample-item">hello-gpuimage</div>
<div class="sample-item">hello-libyuv</div>
<div class="sample-item">hello-renderscript-toolkit</div>
<div class="sample-item">hello-leptonica</div>
<div class="sample-item">hello-pdfium</div>
<div class="sample-item">hello-mupdf</div>
<div class="sample-item">hello-maplibre</div>
<div class="sample-item">hello-zxing</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Vision, ML & speech <span class="sample-group-count">9</span></h3>
<p class="sample-group-desc">Real inference, checked bit-exact against goldens</p>
<div class="samples-grid">
<div class="sample-item">hello-opencv</div>
<div class="sample-item">hello-tflite</div>
<div class="sample-item">hello-litert-llm</div>
<div class="sample-item">hello-pytorch</div>
<div class="sample-item">hello-onnxruntime</div>
<div class="sample-item">hello-ncnn</div>
<div class="sample-item">hello-mediapipe</div>
<div class="sample-item">hello-vosk</div>
<div class="sample-item">hello-tesseract</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Crypto & secure storage <span class="sample-group-count">9</span></h3>
<p class="sample-group-desc">Libraries where a wrong bit is silent, not loud</p>
<div class="samples-grid">
<div class="sample-item">hello-sqlcipher</div>
<div class="sample-item">hello-conscrypt</div>
<div class="sample-item">hello-libsignal</div>
<div class="sample-item">hello-libsodium</div>
<div class="sample-item">hello-argon2</div>
<div class="sample-item">hello-themis</div>
<div class="sample-item">hello-secp256k1</div>
<div class="sample-item">hello-bcrypt</div>
<div class="sample-item">hello-blowfish</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Databases & compression <span class="sample-group-count">11</span></h3>
<p class="sample-group-desc">Storage engines and the codecs around them</p>
<div class="samples-grid">
<div class="sample-item">hello-realm</div>
<div class="sample-item">hello-objectbox</div>
<div class="sample-item">hello-couchbase</div>
<div class="sample-item">hello-wcdb</div>
<div class="sample-item">hello-sqlite-bundled</div>
<div class="sample-item">hello-leveldb</div>
<div class="sample-item">hello-appsearch</div>
<div class="sample-item">hello-mmkv</div>
<div class="sample-item">hello-zstd</div>
<div class="sample-item">hello-snappy</div>
<div class="sample-item">hello-libarchive</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">UI engines <span class="sample-group-count">3</span></h3>
<p class="sample-group-desc">Whole frameworks, not just their leaf libraries</p>
<div class="samples-grid">
<div class="sample-item">hello-qt</div>
<div class="sample-item">hello-reactnative</div>
<div class="sample-item">hello-lynx</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">JS engines & JNI bridges <span class="sample-group-count">8</span></h3>
<p class="sample-group-desc">Runtimes that generate or dispatch code themselves</p>
<div class="samples-grid">
<div class="sample-item">hello-quickjs</div>
<div class="sample-item">hello-duktape</div>
<div class="sample-item">hello-j2v8</div>
<div class="sample-item">hello-javet</div>
<div class="sample-item">hello-lua</div>
<div class="sample-item">hello-javacpp</div>
<div class="sample-item">hello-jna</div>
<div class="sample-item">hello-fbjni</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Networking <span class="sample-group-count">3</span></h3>
<p class="sample-group-desc">Stacks that fork, thread, and hold sockets open</p>
<div class="samples-grid">
<div class="sample-item">hello-cronet</div>
<div class="sample-item">hello-wireguard</div>
<div class="sample-item">hello-libtorrent4j</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">Numeric, physics & parsing <span class="sample-group-count">8</span></h3>
<p class="sample-group-desc">Hot loops, and the text formats around them</p>
<div class="samples-grid">
<div class="sample-item">hello-openblas</div>
<div class="sample-item">hello-fftw</div>
<div class="sample-item">hello-gsl</div>
<div class="sample-item">hello-box2d</div>
<div class="sample-item">hello-bullet</div>
<div class="sample-item">hello-pcre2</div>
<div class="sample-item">hello-libxml2</div>
<div class="sample-item">hello-sentry-ndk</div>
</div>
</div>
<div class="sample-group">
<h3 class="sample-group-title">ARM64 instruction probes <span class="sample-group-count">25</span></h3>
<p class="sample-group-desc">One extension each, asserted against hand-computed goldens</p>
<div class="samples-grid">
<div class="sample-item">hello-neon</div>
<div class="sample-item">hello-neonmisc</div>
<div class="sample-item">hello-fp16</div>
<div class="sample-item">hello-fp16arith</div>
<div class="sample-item">hello-bf16</div>
<div class="sample-item">hello-fp-vector</div>
<div class="sample-item">hello-complex</div>
<div class="sample-item">hello-fcma</div>
<div class="sample-item">hello-fcsel</div>
<div class="sample-item">hello-dotprod</div>
<div class="sample-item">hello-i8mm-bf16</div>
<div class="sample-item">hello-widemul</div>
<div class="sample-item">hello-jscvt</div>
<div class="sample-item">hello-pac-ret</div>
<div class="sample-item">hello-bti</div>
<div class="sample-item">hello-lse</div>
<div class="sample-item">hello-lseatomics</div>
<div class="sample-item">hello-lsepair</div>
<div class="sample-item">hello-lrcpc</div>
<div class="sample-item">hello-ldxp</div>
<div class="sample-item">hello-barriers</div>
<div class="sample-item">hello-ld-interleave</div>
<div class="sample-item">hello-sha-crypto</div>
<div class="sample-item">hello-aes</div>
<div class="sample-item">hello-cntvct</div>
</div>
</div>
</div>
<p class="section-desc" style="margin-top:24px">Beyond the in-tree samples, real unmodified third-party ARM64 APKs are tracked on the <a href="apps.html">Verified Apps</a> page.</p>
</div>
</section>
<!-- Attribution. Last section of the page rather than the shared footer, so it
sits where a reader ends up after the content instead of on every page. -->
<section id="attribution">
<div class="container">
<h2 class="section-title">Attribution</h2>
<p class="attribution-text">
Digitalis is a modification of the <a href="https://source.android.com/" target="_blank" rel="noopener">Android Open Source Project</a>
and its <a href="https://cs.android.com/android/platform/superproject/main/+/main:frameworks/libs/binary_translation/" target="_blank" rel="noopener">Berberis</a>
binary-translation framework, © Google LLC, used under the Apache License 2.0. Android, Berberis,
ANGLE and GFXStream are projects and/or trademarks of Google LLC. Digitalis is an independent project,
not affiliated with, endorsed by, or sponsored by Google.
</p>
<p class="attribution-text">
Arm, AArch64 and NEON are trademarks of Arm Limited. Vulkan and OpenGL ES are trademarks of the Khronos Group.
The sample apps link third-party libraries — among them Qt, React Native, Lynx, OpenCV, TensorFlow Lite,
PyTorch, ONNX Runtime, FFmpeg, WebRTC, Realm and SQLCipher — each the property of its respective owners
and used under its own license.
</p>
<p class="attribution-text">
Third-party application and product names, logos and packages named on this site are trademarks of their
respective owners and appear solely to report interoperability-testing results; no affiliation or endorsement
is implied, and no third-party application is redistributed here.
</p>
</div>
</section>
<!-- Footer -->
{% include footer.html %}
<script src="/assets/theme.js" defer></script>
</body>
</html>