# 24 — the arm64 jit and the llvm backend, actually run both backends were updated when the word went to 64 bits, and neither had been executed since. the jit section of `test.sh` wants `aarch64-linux-gnu-gcc` and `qemu-aarch64` (linux-user). `qemu-system-aarch64` does not satisfy that check. the llvm section wants `llvm-config`. this host had the cross gcc and the system emulators from the bare-metal stage, and not the other two. they were installed here: `qemu-user` 8.2.2 (provides `/usr/bin/qemu-aarch64`), `qemu-user-binfmt`, `libc6-dev-arm64-cross` (the sysroot a static aarch64 link needs), and `llvm-dev` (LLVM 18.1.3, `llvm-config` works). clang 18.1.3 was already present. the suite links the llvm binary with gcc, not clang. ## how each one was built and run the hosted interpreter, for the comparison, is the usual host binary: `gcc -O2 -w -DJTYPE=int core.c io_linux.c`. host gcc is 13.3.0, the machine is x86_64. the jit: ``` aarch64-linux-gnu-gcc -O2 -w -DJTYPE=int -static core.c io_linux.c -o zyj qemu-aarch64 zyj < program.zc ``` `aarch64-linux-gnu-gcc` is 13.3.0. `-static` is what `test.sh` passes, so the binary does not need the aarch64 dynamic loader at run time. the smoke binary was 1,428,296 bytes. `ZYTRACE=1` counts lines containing `bytes of arm64`. the llvm backend: ``` gcc -O2 -w -DJTYPE=int -DZYLLVM $(llvm-config --cflags) core.c io_linux.c \ -o zyl $(llvm-config --ldflags --libs) ``` `llvm-config` is 18.1.3. `ZYTRACE=1` counts lines containing `compiled by llvm`. `ZYHOT=1` compiles every block, not only the hot ones, and `test.sh` checks that `tests/types.zc` then matches the interpreter's stdout by md5. ## what matched a short smoke, before the full script: `examples/hello.zc`, `examples/fact.zc`, `tests/wide.zc` and `tests/o3.zc` on both backends printed the same stdout as the interpreter. `tests/o3.zc` lifted 8 regions on each (`bytes of arm64`, `compiled by llvm`). then `bash test.sh`, which is the existing list, not a new one. the fixpoint stayed 91158 words and `genome.h` matched. the interpreter, the microcore, the 172032-word compiler, the 32768-word run-only image, and both virt boards (7 boots each) passed as before. the jit ran that same `run` list under qemu-user, plus the 8-region count and a self-compile compared with `g1.bin`. the llvm binary ran the same list, plus the 8-region count, the `ZYHOT=1` md5, and its own self-compile. the second full run, after the fix below, was 292 passed, 0 failed. ## the one failure the first full run was 291 passed, 1 failed: `jit virtual enhancements`, stdout `100 0 343 3,2 ` instead of `100 0 343 3,2 5 -2 0`. exit status 0. the interpreter and the llvm backend both printed the full line. `tests/enhance.zc` installs `noisy` as vm code whose body does a `putc`. `lift_vm` refuses i/o and `install` returns `-4`. the compiler, when that return is negative, sets the fallback bit and emits a call to `soft_noisy` instead of the opcode. the prints that did come out are `clampadd`, `cube` and `divmod`, which install cleanly. the halt is the next call, `noisy(4)`. opcode 21 in the jit is a `blr` to `inst_hook`, which returns `int`, then a 64-bit store of `x0` onto the data stack. on aarch64 a write to `w0` zeroes bits 63:32. `-4` in `w0` is `0x00000000fffffffc` in `x0`, which as a cell is 4294967292, and `r < 0` in the compiler is false. the fallback bit stays clear, the compiler emits the opcode, the slot was never installed, and the translator's unwired path is `movn x0, #0` and a branch to the exit stub. that is a clean halt, which is why the status was 0 and the line simply stopped. the llvm path does not have this hole. its install helper is `static Cell linstall(Cell d) { return install((int)d); }`, and the C conversion sign-extends. the interpreter assigns `install`'s `int` straight into a `Cell`. the fix is one instruction after that `blr`: `sxtw x0, w0` (`0x93407c00`), then the store. `tests/enhance.zc` under `qemu-aarch64` then printed `100 0 343 3,2 5 -2 0`, and `examples/wiring.zc` still printed `16 1234 25 4/9`. the genome did not change. the instruction is in the translator, so a Darwin build of the same core gets it too, but that build was not run. ## what was not run - the Darwin jit. `core.c` takes a different path there (`MAP_JIT`, `pthread_jit_write_protect_np`, `sys_icache_invalidate`). this machine is x86_64 Linux. qemu-user executes the linux aarch64 ELF; it does not execute that path. - real aarch64 hardware. every jit instruction ran inside qemu-user 8.2.2. - the jit and llvm backends on the small and run-only maps, and on the bare-metal boards. `test.sh` runs those maps on the interpreter and the microcore. the two native backends stay on the default 1,048,576-word genome.